且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

WPF中动态添加控件,并为控制指定样式

更新时间:2022-08-16 11:50:12

有个需求,需要为List中的每个Item(List中是基本类型)创建一个TextBlock显示其中的值。如果在Xaml中直接写控件的话,可能不能达到理想的效果(不能使用ItemsControls这样的控件)。那么只能通过程序动态添加。特写此记录。
第一种方式:
将样式写在Xaml中,或者自定义一个用户控件。

            TextBlock tb = new TextBlock();
            var textBinding = new Binding("MissionPoints[" + x + "]");
            textBinding.Mode = BindingMode.TwoWay;
            tb.SetBinding(TextBlock.TextProperty, textBinding);
            // 将下面资源写在Xaml中,通过查找资源来设置Style
            //        <Style x:Key="tbStyle" TargetType="{x:Type TextBlock}">
            //    <Style.Triggers>
            //        <DataTrigger  Binding="{Binding RelativeSource={RelativeSource Self},Path=Text,Converter={StaticResource dc}}"  Value="True">
            //            <Setter Property="Foreground" Value="Red" ></Setter>
            //        </DataTrigger>
            //    </Style.Triggers>
            //</Style>
             tb.Style = this.FindResource("tbStyle") as Style;

            this.grid1.Children.Add(tb);
            Grid.SetRow(tb, x);   

这种方式是将样式写在Xaml中,不便于理解WPF的实现模式。

第二种方式:完全使用C#代码实现。

            TextBlock tb = new TextBlock();
            var textBinding = new Binding("MissionPoints[" + x + "]");
            textBinding.Mode = BindingMode.TwoWay;
            tb.SetBinding(TextBlock.TextProperty, textBinding);
         
            Binding dtBinding = new Binding();
            dtBinding.Path = new PropertyPath("Text");
            dtBinding.RelativeSource = new RelativeSource(RelativeSourceMode.Self);
            dtBinding.Converter = new DataConverter();

            DataTrigger dt = new DataTrigger();
            dt.Binding = dtBinding;
            dt.Value = true;
            Setter setter = new Setter();
            setter.Property = TextBlock.ForegroundProperty;
            var brush = new System.Windows.Media.SolidColorBrush();
            brush.Color = Color.FromRgb(255, 0, 0);
            setter.Value = brush;
            dt.Setters.Add(setter);
            Style style = new Style();
            style.TargetType = typeof(TextBlock);
            style.Triggers.Add(dt);
            tb.Style = style;

            this.grid1.Children.Add(tb);
            Grid.SetRow(tb, x);         

第二种方式完全使用C#实现功能。便于理解WPF的实现原理。但我最初的触发器没有实现。原因是少写了判断 的值 。

 dt.Value = true;

所以写代码的时候要仔细。

public class DataConverter : IValueConverter

{
    #region IValueConverter 成员

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null) return false;
        if (string.IsNullOrEmpty(value.ToString())) return false;
        if (!Regex.IsMatch(value.ToString(), "^[1-9]\\d*$")) return false;
        return System.Convert.ToInt32(value) > 0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    #endregion
}

当值大于0时前景色设置为红色。