带有样式和日期触发器的 DataTemplate 来自代码

gul*_*aek 3 .net c# wpf styles datatemplate

我创造了这个DataTemplate,但我无法弄清楚如何添加style一个DataTriggerIMG变量。

我希望img根据Suppliers[i].Stock(int)的值显示不同的图像

资源图标

Properties.Resources.InStock     => Suppliers[i].Stock > 0
Properties.Resources.OutOfStock  => Suppliers[i].Stock = 0
Properties.Resources.Unknown     => Suppliers[i].Stock = null
Run Code Online (Sandbox Code Playgroud)

我的代码到目前为止。

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;
}
Run Code Online (Sandbox Code Playgroud)

我认为触发器可以工作的方式是,创建一个显示 InStock 图标的默认样式,然后打开两个触发器Stock = null,另一个用于Stock = 0

由于我是动态执行此操作,因此无法使用 xaml,并且其他所有内容都可以使用DataTemplate.

解决方案

在@akjoshi 的帮助下,这就是我最终使用的。

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
}
Run Code Online (Sandbox Code Playgroud)

akj*_*shi 5

我认为你的想法是对的,代码应该是这样的 -

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); 
Run Code Online (Sandbox Code Playgroud)

我建议您查看 Sacha 的以下精彩文章,与此相关-

WPF:如何在代码/和神奇内容中创建样式

作为旁注,如FrameworkElementFactory弃用,最好定义此样式Resources/xaml并用于FindResource()设置它。如果一些重新设计可以使您实现这一目标,那么我建议您这样做。