【问题标题】:SetCurrentValue myLabel.BackgroundProperty without breaking the bindingSetCurrentValue myLabel.BackgroundProperty 不破坏绑定
【发布时间】:2013-03-18 11:35:33
【问题描述】:

我有三个文本框和一个标签。 使用 Multiconverter 将标签绑定到文本框中的文本。

XAML:

<Label Name="lbl" Content="Label" HorizontalAlignment="Left" Margin="336,128,0,0" VerticalAlignment="Top" Height="57" Width="93">
        <Label.Background>
            <MultiBinding Converter="{StaticResource converta}">
                <Binding ElementName="R" Path="Text" Mode="TwoWay" />
                <Binding ElementName="G" Path="Text" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" />
                <Binding ElementName="B" Path="Text" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" />
            </MultiBinding>

        </Label.Background>
    </Label> 
    <TextBox Name="R" HorizontalAlignment="Left" Height="23" Margin="250,214,0,0" TextWrapping="Wrap" Text="255" VerticalAlignment="Top" Width="120"/>
    <TextBox Name="B" HorizontalAlignment="Left" Height="23" Margin="271,242,0,0" TextWrapping="Wrap" Text="255" VerticalAlignment="Top" Width="120"/>
    <TextBox Name="G" HorizontalAlignment="Left" Height="23" Margin="155,275,0,0" TextWrapping="Wrap" Text="255" VerticalAlignment="Top" Width="120"/>

转换器

class converter : IMultiValueConverter
{

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {

            return new System.Windows.Media.SolidColorBrush(Color.FromRgb(System.Convert.ToByte((values[0] as string)), System.Convert.ToByte((values[1] as string)), System.Convert.ToByte((values[2] as string))));

    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        byte R = (value as System.Windows.Media.Color?).Value.R;
        byte G = (value as System.Windows.Media.Color?).Value.G;
        byte B = (value as System.Windows.Media.Color?).Value.B;
        return new string[] {System.Convert.ToString(R),System.Convert.ToString(G),System.Convert.ToString(B)};

    }
    }

(显然,在现实世界中,我会添加验证和类型检查)。

现在我想添加一个按钮来设置标签背景,像这样简单:

    lbl.Background= new SolidColorBrush(Color.FromRgb(
System.Convert.ToByte(121), 
System.Convert.ToByte(43), 
System.Convert.ToByte(15)));

显然,它破坏了绑定。 所以我尝试:

    SetCurrentValue(lbl.BackgroundProperty, 
new SolidColorBrush(
Color.FromRgb(System.Convert.ToByte(121), 
System.Convert.ToByte(43), 
System.Convert.ToByte(15))));

但是 VS 抱怨

成员“System.Windows.Controls.Control.BackgroundProperty”不能 通过实例引用访问;用类型名称限定它 而是

如何在代码中设置标签背景的值而不破坏绑定?

注意:这是 WPF,.Net 4.5

【问题讨论】:

    标签: c# wpf xaml binding


    【解决方案1】:

    错误是自我描述的,它告诉你 lbl.BackgroundProperty 不能这样设置。以下是执行此操作的正确方法。

            lbl.SetCurrentValue(BackgroundProperty,
                                       new SolidColorBrush(Color.FromRgb(System.Convert.ToByte(121),
                                                                         System.Convert.ToByte(43),
                                                                         System.Convert.ToByte(15))));
    

    【讨论】:

    • 嗨,TYY,这是一个很好的答案,我基本上实现了我想要的(绑定没有损坏)。就在我将此标记为答案之前,知道为什么在我的场景中没有调用 ConvertBack 方法吗? (并不是说它不起作用,它没有被调用,即如果我在 ConvertBack() 方法中添加 MessageBox.Show() 方法,它根本不会被调用!)
    • 您必须检查该属性是否允许双向通信。只有在那时才会触发转换。
    • 我在 MSDN 上没有看到任何内容,但无论如何,非常感谢您的帮助!
    【解决方案2】:

    我可能会将 RGB 值作为依赖属性,您可以根据需要从后面的代码中更改它们。

    结果

    XAML

    <Window x:Class="test.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:local="clr-namespace:test"
            DataContext="{Binding RelativeSource={RelativeSource Self}}"
            Title="MainWindow" Height="350" Width="525">
    
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid>
                <Grid.Background>
                    <MultiBinding Converter="{local:RGBtoBrushConverter}">
                        <MultiBinding.Bindings>
                            <Binding Path="R"/>
                            <Binding Path="G"/>
                            <Binding Path="B"/>
                        </MultiBinding.Bindings>
                    </MultiBinding>
                </Grid.Background>
            </Grid>
    
            <Grid Grid.Row="1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
    
                <TextBox Grid.Column="0" Text="{Binding R, UpdateSourceTrigger=PropertyChanged}"/>
                <TextBox Grid.Column="1" Text="{Binding G, UpdateSourceTrigger=PropertyChanged}"/>
                <TextBox Grid.Column="2" Text="{Binding B, UpdateSourceTrigger=PropertyChanged}"/>
            </Grid>
        </Grid>
    </Window>
    

    代码

    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Markup;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace test
    {
    
        public class RGBtoBrushConverter : MarkupExtension, IMultiValueConverter
        {
            static RGBtoBrushConverter converter;
            public RGBtoBrushConverter() { }
            public override object ProvideValue(IServiceProvider serviceProvider)
            {
                if (converter == null) converter = new RGBtoBrushConverter();
                return converter;
            }
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                try
                {
                    byte R = System.Convert.ToByte(values[0]);
                    byte G = System.Convert.ToByte(values[1]);
                    byte B = System.Convert.ToByte(values[2]);
                    return new System.Windows.Media.SolidColorBrush(Color.FromArgb(byte.MaxValue, R, G, B));
                }
                catch { return Brushes.Purple; }
            }
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
    
        public partial class MainWindow : Window
        {
            public int R
            {
                get { return (int)GetValue(RProperty); }
                set { SetValue(RProperty, value); }
            }
            public static readonly DependencyProperty RProperty = DependencyProperty.Register("R", typeof(int), typeof(MainWindow), new PropertyMetadata(0));
    
            public int G
            {
                get { return (int)GetValue(GProperty); }
                set { SetValue(GProperty, value); }
            }
            public static readonly DependencyProperty GProperty = DependencyProperty.Register("G", typeof(int), typeof(MainWindow), new PropertyMetadata(0));
            public int B
            {
                get { return (int)GetValue(BProperty); }
                set { SetValue(BProperty, value); }
            }
            public static readonly DependencyProperty BProperty = DependencyProperty.Register("B", typeof(int), typeof(MainWindow), new PropertyMetadata(0));
    
    
            public MainWindow()
            {
                InitializeComponent();
            }
        }
    }
    

    【讨论】:

    • 嗨,Andy,对于所概述的小场景,这可能是一个可行的解决方案,因此符合条件。但是您没有指定 ConvertBack 方法,因此设置依赖属性不会更改文本框中的文本,因此无需设置 lbl.BackgroundProperty 的值,因为我们可以显式设置文本值文本框。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    • 1970-01-01
    • 1970-01-01
    • 2020-04-30
    • 2020-12-08
    • 2011-04-19
    相关资源
    最近更新 更多