具有只读属性的TwoWay MultiBinding

时间:2009-11-19 23:48:46

标签: wpf data-binding

如何跳过更新MultiBinding的某些子绑定?我已经在代码隐藏中定义了(我在XAML中遇到了一些麻烦,我觉得这并不重要 - 毕竟代码隐藏不是那么表达XAML)a MultiBinding它有两个只读属性和一个生成单个值的普通属性。如果ConvertBack,则不修改只读属性(它们维持其值)并且仅更改普通属性。

在定义MultiBinding时,整个MultiBinding设置为TwoWay,但是设置适当的特定子绑定(前两个到OneWay和第三个{{1} }})。


问题发生在我自己的控件中。然而,为了便于演示,我将其简化为较小的控件。此示例中显示的控件是一个类似TwoWay的控件,允许选择[0.0; 1.0]范围。所选值由拇指表示,并显示为Slider

基本上,控件是由1行x 3列DependencyProperty构建的,其中拇指位于中间列。要正确定位拇指,左列必须指定与所选位置对应的宽度。然而,这个宽度还取决于整个控件的实际宽度和拇指本身的实际宽度(这是因为位置是[0.0; 1.0]范围内的相对值)。

当拇指移动时,位置应该适当更新,但拇指宽度和控制宽度显然不会改变。

代码按预期工作,但是在拇指移动期间在IDE中运行时,当Grid尝试将值设置为这两个只读属性时,输出窗口会混乱出现异常信息。我怀疑它没有害处,但有点烦人和误导。而且这意味着代码执行了其他操作,然后我希望它能够执行,因为我不想设置这些属性(这非常重要,以防它们不是只读的,这实际上会修改它们。)

备注部分中的

MultiBinding documentation提到允许单个子绑定覆盖MultiBinding模式值,但它似乎不起作用。

也许这可以通过以某种方式表达对控件和拇指宽度(只读属性)的依赖性以某种方式解决。例如,单独注册其通知并在更改时强制执行更新。然而,这对我来说似乎并不自然。另一方面,MultiBinding执行,因为所有左列宽度都取决于这三个属性。


以下是示例XAML代码。

MultiBinding

这是相应的代码隐藏

<UserControl x:Class="WpfTest.ExampleUserControl"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 <Grid>
  <Grid.RowDefinitions>
   <RowDefinition />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
   <ColumnDefinition x:Name="leftColumn" />
   <ColumnDefinition x:Name="thumbColumn" Width="Auto" />
   <ColumnDefinition />
  </Grid.ColumnDefinitions>
  <!-- Rectangle used in the left column for better visualization. -->
  <Rectangle Grid.Column="0">
   <Rectangle.Fill>
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
     <GradientStop Color="Black" Offset="0" />
     <GradientStop Color="White" Offset="1" />
    </LinearGradientBrush>
   </Rectangle.Fill>
  </Rectangle>
  <!-- Thumb representing the Position property. -->
  <GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Center" />
  <!-- Rectangle used in the right column for better visualization. -->
  <Rectangle Grid.Column="2">
   <Rectangle.Fill>
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
     <GradientStop Color="White" Offset="0" />
     <GradientStop Color="Black" Offset="1" />
    </LinearGradientBrush>
   </Rectangle.Fill>
  </Rectangle>
 </Grid>
</UserControl>

2 个答案:

答案 0 :(得分:10)

最后我自己找到了解决方案。实际上它在documentation - 我不知道我是如何错过的,但我付出了沉重的代价(浪费时间)。

根据文档ConvertBack应该返回Binding.DoNothing关于没有设置值的位置(特别是需要OneWay绑定)。另一个特殊值是DependencyProperty.UnsetValue

这不是一个完整的解决方案,因为现在IMultiValueConverter实现必须知道返回特殊值的位置。但是我认为这个解决方案涵盖了大多数合理的案例。

答案 1 :(得分:4)

看起来MultiBinding无法正常工作。在我的练习之前,我已经看到了一些意想不到的行为(类似于你的行为)。你也可以在转换器中插入断点或一些跟踪,你可以找到一些有趣的事情,关于哪些转换器和何时被调用。 因此,如果可能,您应该避免使用MultiBinding。例如。您可以在视图模型中添加特殊属性,该属性将在其setter中设置mutable属性的值,并使用其getter中的所有三个属性返回所需的值。它类似于属性中的MultiValueConverter =)。

希望它有所帮助。