DataTemplate with Style and DateTriggers from code

.net, c#, datatemplate, styles, wpf

Solution

I think your idea is right, code should be something like this -

var img = new FrameworkElementFactory(typeof(Image)); 
img.SetValue(Image.SourceProperty, "InStockImagePath");

Style style = new Style();
style.TargetType = typeof(Image);

DataTrigger zeroDataTrigger = new DataTrigger();
zeroDataTrigger.Binding = new Binding("Suppliers[" + i + "].Stock");
zeroDataTrigger.Value = 0;
zeroDataTrigger.Setters.Add(new Setter(Image.SourceProperty, "OutOfStockImagePath"));

DataTrigger nullDataTrigger = new DataTrigger();
nullDataTrigger.Binding = new Binding("Suppliers[" + i + "].Stock");
nullDataTrigger.Value = null;
nullDataTrigger.Setters.Add(new Setter(Image.SourceProperty, "unknownImagePath"));

style.Triggers.Add(zeroDataTrigger);
style.Triggers.Add(nullDataTrigger);

img.SetValue(Image.StyleProperty, style);
wp.AppendChild(img); 

I suggest you to look at following great article from Sacha, related to this -

WPF: How to create Styles in code/and magical Content

As a sidenote, as `FrameworkElementFactory` is deprecated, it would be better to define this style in `Resources/xaml` and use `FindResource()` to set it. If some redesigning can make you achieve this then I would suggest you to do that.

Problem

I created this `DataTemplate`, but I can't figure out how to add a `style` with a `DataTrigger` to the img variable. I would like img to show different images depending on the value of `Suppliers[i].Stock` (int) Resource Icons ``` Properties.Resources.InStock => Suppliers[i].Stock > 0 Properties.Resources.OutOfStock => Suppliers[i].Stock = 0 Properties.Resources.Unknown => Suppliers[i].Stock = null ``` My code so far. ``` private DataTemplate GetStockTemplate(int i) { var template = new DataTemplate(); var wp = new FrameworkElementFactory(typeof (WrapPanel)); wp.SetValue(FrameworkElement.HorizontalAlignmentProperty, HorizontalAlignment.Right); wp.SetValue(WrapPanel.OrientationProperty, Orientation.Horizontal); var tx = new FrameworkElementFactory(typeof (TextBox)); tx.SetBinding(TextBox.TextProperty, new Binding("Suppliers[" + i + "].Stock") {StringFormat = "{0:n0}"}); tx.SetValue(TextBoxBase.IsReadOnlyProperty, true); tx.SetValue(Control.BorderThicknessProperty, new Thickness(0)); tx.SetValue(Control.BackgroundProperty, Brushes.Transparent); tx.SetValue(TextBox.TextAlignmentProperty, TextAlignment.Right); wp.AppendChild(tx); var img = new FrameworkElementFactory(typeof (Image)); wp.AppendChild(img); template.VisualTree = wp; template.Seal(); return template; } ``` The way I think the trigger could work is, create a default style showing the InStock icon, Then have two triggers on for `Stock = null` and another for `Stock = 0` Since I'm doing this dynamically I can't use xaml, and I got everything else working with `DataTemplate`. Solution With help from @akjoshi this is what I ended up using. ``` var img = new FrameworkElementFactory(typeof(Image)); var binding = new Binding("Suppliers[" + i + "].Stock") {Converter = new StockIconConverter()}; img.SetBinding(Image.SourceProperty, binding); wp.AppendChild(img); class StockIconConverter :IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null || (int)value < 0) return ConvertIconToBitmapImage(Properties.Resources.Unknown); return ConvertIconToBitmapImage((int)value == 0 ? Properties.Resources.OutOfStock : Properties.Resources.InStock); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } #region Helper private static BitmapImage ConvertIconToBitmapImage(Icon icon) { var bitmap = icon.ToBitmap(); var ms = new MemoryStream(); bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png); var bImg = new BitmapImage(); bImg.BeginInit(); bImg.StreamSource = new MemoryStream(ms.ToArray()); bImg.CreateOptions = BitmapCreateOptions.None; bImg.CacheOption = BitmapCacheOption.Default; bImg.EndInit(); bImg.Freeze(); ms.Close(); return bImg; } #endregion } ```

Original source

Related problems