Linking the displayed template (path) with the data model / How to make paths the same size

Background

[Feel free to skip this]

I am creating a program that relates to horses, their owners and owners of racing flowers (silk). This question is about a UserControl called SilksControl , which acts as a view for JockeySilks .

To represent silks, I use the following class of enumerations:

 public class JockeySilks { public BodyPatterns BodyPattern { get; set; } public Colour BodyColour1 { get; set; } public Colour BodyColour2 { get; set; } public SleevePatterns SleevePattern { get; set; } public Colour SleeveColour1 { get; set; } public Colour SleeveColour2 { get; set; } public CapPatterns CapPattern { get; set; } public Colour CapColour1 { get; set; } public Colour CapColour2 { get; set; } } 

As you can see, different elements and colors for each jockey silk element. The main part of each item is [Item] Color1, and the template is populated with [Item] Color2.

The core SilksControl is a ViewBox containing a Canvas , which in turn contains a Path s number. I drew each of the patterns as a Path inside a child Canvas .

Here is the image. In this example, CapPattern and BodyPattern set to Plain , and ArmPattern set to Chevrons .

Problem

I am trying to find a better way to set a template based on WPF data binding. However, there is one problem: each Path template has different values ​​and sizes for Canvas.Top and Canvas.Left . By β€œbetter way” I mean something that is simple, easy to read, and easy to implement.

The approaches I was thinking

  • Switching the path to the code is probably something like pthCapPattern = CapPatterns[SilksModel.CapPattern] , where CapPatterns is a Dictionary<CapPattern,Path> or there may be access to it from resources
    • But not binding, I have to implement some events and stuff
  • Linking the contents of some control / panel with SilksModel.[Item]Pattern with a converter that generates / draws a path from resources / dictionary
    • What kind of control?
    • You may need to generate an entire new path.
    • Several resource intensive
  • Have all Path in XAML and change the visibility of each
    • It is just uncomfortable and strange.
  • Determine how to reconcile differences in size, then create 1 path and bind it to the Path.Data property (perhaps there are several StreamGeometry in the resources, using a converter to go from enumeration to StreamGeometry )
    • I don’t know how to give them the same dimensions and therefore Canvas offsets. Canvas

So, solution 4 is my preferred solution, but as I mentioned, I have no idea how I can do this, and my Googling skills cannot come up with anything useful. Otherwise, solution 2 will be the next best, but I do not know any containers that offer the same functionality as the canvas and offer binding to children / content.

EDIT 1:

 <Canvas x:Name="SPatterns" Height="173" Canvas.Left="6.8" Canvas.Top="107" Width="236.6"> <Path x:Name="Chevrons" Fill="{Binding SilksModel.BodyColour2, Converter={StaticResource DBColourToColorConverter}, ElementName=root" Height="134.125" Canvas.Left="1.087" Stretch="Fill" Stroke="Black" Canvas.Top="21.667" Width="234.168" Data="M21.750001,94.749999 L34.000002,117.66218 30.625003,133.62501 17.000006,113.32909 0.5,126.75 3.2500048,108.125 z M212.418,93.416999 L230.918,106.79199 233.668,125.41701 217.168,111.99609 203.543,132.292 200.168,116.32917 z M32.25,48.374999 L44.250004,72.249999 40.625004,90.249999 28.000003,68.581336 7.750001,82.249999 11.665709,64.166339 z M201.918,47.041991 L222.50229,62.833335 226.418,80.916991 206.168,67.248336 193.543,88.916999 189.918,70.916991 z M41,1.8329993 L55.000002,28.166337 51.66667,45.832999 37.333336,23.499837 16.666001,37.417269 21.66571,19.418135 z M193.168,0.5 L212.50229,18.085143 217.502,36.084262 196.83467,22.166836 182.50133,44.499991 179.168,26.833333 z" /> <!-- More SleevePatterns --> </Canvas> 
+4
source share
1 answer

It may not be the cleanest solution, but something like this work for you (Obviously, would you move the geometry initialization from the constructor)?

You can create your proposed Dictionary<CapPattern,Path> object and fill it with information about your path, as well as apply Transform to Geometry to give it the necessary dimensions / offset relative to Canvas .

 public partial class Horses : UserControl, INotifyPropertyChanged { public enum CapPattern { ChevronPattern, SomeOtherPattern }; public Dictionary<CapPattern, Geometry> Patterns { get; set; } private Geometry currentPath; public Geometry CurrentPath { get { return this.currentPath; } set { this.currentPath = value; NotifyPropertyChanged(); } } public Horses() { Patterns = new Dictionary<CapPattern, Geometry>(); Patterns.Add( CapPattern.ChevronPattern, Geometry.Combine( Geometry.Parse("M21.750001,94.749999 L34.000002,117.66218 30.625003,133.62501 17.000006,113.32909 0.5,126.75 3.2500048,108.125 z M212.418,93.416999 L230.918,106.79199 233.668,125.41701 217.168,111.99609 203.543,132.292 200.168,116.32917 z M32.25,48.374999 L44.250004,72.249999 40.625004,90.249999 28.000003,68.581336 7.750001,82.249999 11.665709,64.166339 z M201.918,47.041991 L222.50229,62.833335 226.418,80.916991 206.168,67.248336 193.543,88.916999 189.918,70.916991 z M41,1.8329993 L55.000002,28.166337 51.66667,45.832999 37.333336,23.499837 16.666001,37.417269 21.66571,19.418135 z M193.168,0.5 L212.50229,18.085143 217.502,36.084262 196.83467,22.166836 182.50133,44.499991 179.168,26.833333 z"), Geometry.Empty, GeometryCombineMode.Union, new TranslateTransform(0, 0))); Patterns.Add( CapPattern.SomeOtherPattern, Geometry.Combine( Geometry.Parse("M21.750001,94.749999 L34.000002,117.66218 30.625003,133.62501 17.000006,113.32909 0.5,126.75 3.2500048,108.125 z M212.418,93.416999 L230.918,106.79199 233.668,125.41701 217.168,111.99609 203.543,132.292 200.168,116.32917 z M32.25,48.374999 L44.250004,72.249999 40.625004,90.249999 28.000003,68.581336 7.750001,82.249999 11.665709,64.166339 z M201.918,47.041991 L222.50229,62.833335 226.418,80.916991 206.168,67.248336 193.543,88.916999 189.918,70.916991 z M41,1.8329993 L55.000002,28.166337 51.66667,45.832999 37.333336,23.499837 16.666001,37.417269 21.66571,19.418135 z M193.168,0.5 L212.50229,18.085143 217.502,36.084262 196.83467,22.166836 182.50133,44.499991 179.168,26.833333 z"), Geometry.Empty, GeometryCombineMode.Union, new TranslateTransform(20, 30))); InitializeComponent(); } // INotifyPropertyChanged implementaton. } 

In my layout, I populated the ComboBox from this dictionary, which sets the CurrentPath property, which is bound to the Path in the Canvas :

 <Grid> <StackPanel> <ComboBox ItemsSource="{Binding Path=Patterns}" SelectedValue="{Binding Path=CurrentPath}" SelectedValuePath="Value" DisplayMemberPath="Key"/> <Canvas> <Path Data="{Binding Path=CurrentPath}" Stroke="Black" StrokeThickness="1" /> </Canvas> </StackPanel> </Grid> 

You would keep the binding for Fill and other properties.

Another approach might be to create a small Class that contained your Path information along with the required Top , Left , Transform or any other information needed to place the template. Then you can bind the list of these objects to the ComboBox in the same way as above, and bind all the necessary properties to the Canvas and Path to the properties of the currently selected object.

Edit:

You can also customize your conversions to ResourceDictionary in the following lines:

 <Path x:Name="Chevrons" Fill="{Binding SilksModel.BodyColour2, Converter={StaticResource DBColourToColorConverter}, ElementName=root" Data="M21.750001,94.749999 L34.000002,117.66218 30.625003,133.62501 17.000006,113.32909 0.5,126.75 3.2500048,108.125 z M212.418,93.416999 L230.918,106.79199 233.668,125.41701 217.168,111.99609 203.543,132.292 200.168,116.32917 z M32.25,48.374999 L44.250004,72.249999 40.625004,90.249999 28.000003,68.581336 7.750001,82.249999 11.665709,64.166339 z M201.918,47.041991 L222.50229,62.833335 226.418,80.916991 206.168,67.248336 193.543,88.916999 189.918,70.916991 z M41,1.8329993 L55.000002,28.166337 51.66667,45.832999 37.333336,23.499837 16.666001,37.417269 21.66571,19.418135 z M193.168,0.5 L212.50229,18.085143 217.502,36.084262 196.83467,22.166836 182.50133,44.499991 179.168,26.833333 z" Stroke="Black" StrokeThickness="1"> <Path.RenderTransform> <TranslateTransform X="20" Y="120"/> </Path.RenderTransform> </Path> 
+1
source

Source: https://habr.com/ru/post/1495106/


All Articles