WPF:更改所有数据绑定的路径

时间:2013-12-03 13:16:32

标签: wpf xaml data-binding

我试图在用户点击按钮时更改窗口中的所有数据绑定。 注意:以下代码为伪。

假设我们有一个名为sensor的类:

public class Sensor : INotifyPropertyChanged {
  public int HighVal {get; set;}
  public int LowVal {get; set;}
}

我们绑定的以下模型:

public class SomeModel {
  public Sensor MovementSensor {get; set;}
  public Sensor TemperatureSensor {get; set;}
  public Sensor BarometerSensor {get; set;}
}

在我的xaml中,我想以下列方式绑定:

<TextBox Text="{Binding MyModel.MovementSensor.HighVal}"/>
<TextBlock Text="{Binding MyModel.BarometerSensor.HighVal}"/>

我希望有一个按钮(或类似的东西)点击后,会将所有数据绑定的路径从HighVal改为LowVal,例如

<TextBox Text="{Binding MyModel.MovementSensor.LowVal}"/>
<TextBlock Text="{Binding MyModel.BarometerSensor.LowVal}"/>

是否有一种优雅的方式来执行此操作而不迭代窗口中的所有数据绑定?

谢谢!

1 个答案:

答案 0 :(得分:2)

您可以使用与传感器的两个值连接的MultiBinding和第三个属性来确定当前值:

<TextBlock>
    <TextBlock.Resources>
        <y:SensorValueConverter x:Key="SVC"></y:SensorValueConverter>
    </TextBlock.Resources>
    <TextBlock.Text>
        <MultiBinding Converter="{StaticResource SVC}">            
            <Binding Path="MyModel.BarometerSensor.HighVal" />
            <Binding Path="MyModel.BarometerSensor.LowVal" />
            <Binding Path="MyModel.BarometerSensor.SelectedVal" />    
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

在Windows标记中指定转换器的命名空间,但您必须替换“YOUR-PROJECTNAME”占位符:

<Window x:Class="..."
        ...
        xmlns:y="clr-namespace:YOUR-PROJECTNAME">

我已经通过属性SelectedVal扩展了Sensor类,它存储了应该在TextBox中显示的值。将其更改为“高”或“低”将立即更新TextBox的绑定。

public enum SelectedValue
{
    High,
    Low
}

public class Sensor : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;       

    public int HighVal {get; set;}
    public int LowVal {get; set;}

    SelectedValue selval = SelectedValue.High;
    public SelectedValue SelectedVal
    {
        get
        {
            return selval;
        }
        set
        {
            selval = value;
            PropertyChanged(this, new PropertyChangedEventArgs("SelectedVal"));
        }
    }
}

现在最重要的部分,Binding的ValueConverter将根据SelectedVal的状态选择正确的值(类CultureInfo是System.Globalization命名空间):

public class SensorValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {         
        SelectedValue val = (SelectedValue)values[2];

        if (val == SelectedValue.High)
        {
            return values[0].ToString();
        }
        else
        {
            return values[1].ToString();
        }
    }

    public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
    {

        throw new NotImplementedException();

    }
}

要更改传感器的选定值,您需要修改SelectedVal属性:

MyModel.BarometerSensor.SelectedVal = SelectedValue.Low

<强>更新
要将绑定分配给多个元素,可以在单独的文件(Styles.xaml)中定义样式:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:y="clr-namespace:YOUR-PROJECTNAME">

    <y:SensorValueConverter x:Key="SVC"></y:SensorValueConverter>
    <Style x:Key="ValStyle" TargetType="TextBlock">
        <Setter Property="Text">
            <Setter.Value>
                <MultiBinding Converter="{StaticResource SVC}">
                    <Binding Path="MyModel.BarometerSensor.HighVal" />
                    <Binding Path="MyModel.BarometerSensor.LowVal" />
                    <Binding Path="MyModel.BarometerSensor.SelectedVal" />
                </MultiBinding>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

要从其他窗口使用此样式,只需将此行放在窗口的资源中:

<ResourceDictionary Source="Styles.xaml"></ResourceDictionary>

最后,您需要将创建的样式分配给应显示值的所有TextBlock:

<TextBlock Style="{StaticResource ValStyle}"></TextBlock>

对于只有一个属性的传感器,您可以在Styles.xaml中创建另一个必须仅绑定到一个属性的样式:

<Style x:Key="SpecialValStyle" TargetType="TextBlock">
    <Setter Property="Text">            
        <Binding Path="MyModel.BarometerSensor.HighVal" />
    </Setter>
</Style>