2011-02-02 81 views
31

OneWayToSource绑定似乎打破了.NET 4.0OneWayToSource绑定似乎打破了.NET 4.0

我有这个简单的一块XAML中

<StackPanel> 
    <TextBox Text="{Binding TextProperty, Mode=OneWayToSource}"/> 
    <Button/> 
</StackPanel> 

和我后面的代码看起来像这样

public MainWindow() 
{ 
    InitializeComponent(); 
    this.DataContext = this; 
} 
private string m_textProperty; 
public string TextProperty 
{ 
    get 
    { 
     return "Should not be used in OneWayToSource Binding"; 
    } 
    set 
    { 
     m_textProperty = value; 
    } 
} 

在.NET 3.5中这可以像你可能除外。放入TextBox一些文本,按Tab键使其失去焦点,而TextProperty更新与任何文本是在TextBox

进入在.NET 4.0,如果我键入TextBox一些文字,然后按选项卡使它失去焦点,TextBox恢复为TextProperty(意思是“不应用于OneWayToSource绑定”)的值。这是否重新阅读了.NET 4.0中的OneWayToSource Binding?我只是想TextBox将其价值推到TextProperty而不是相反。

更新
加入悬赏这个问题,因为这已经成为我的项目市长不便,我想知道,这种情况已经改变的原因。看起来,绑定已更新源后调用get。这是在.NET 4.0中绑定的OneWayToSource所需的行为吗?

如果是

  • 知道是怎么在3.5的工作方式的问题?
  • 这种新行为在哪些情况下更好?

或者是这样,其实我们可以希望错误得到固定在未来的版本?

回答

9

卡尔Shifflett的博客和@ Simpzon的答案已经涵盖为什么他们加入这个功能,为什么它是不适合的属性总是会得到什么设置有问题。在你自己的代码中,你总是使用一个具有合适语义的中间属性来绑定,并使用具有所需语义的内部属性。我会将中间属性称为“阻塞”属性,因为它会阻止吸气剂到达您的内部属性。

但是,如果您无法访问要设置属性的实体的源代码,并且您想要旧的行为,则可以使用转换器。

这里是一个阻塞转换器状态:

public class BlockingConverter : IValueConverter 
{ 
    public object lastValue; 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return lastValue; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     lastValue = value; 
     return value; 
    } 
} 

,你可以用它为你的例子是这样的:

<Grid> 
    <Grid.Resources> 
     <local:BlockingConverter x:Key="blockingConverter" x:Shared="False"/> 
    </Grid.Resources> 
    <StackPanel> 
     <TextBox Text="{Binding TextProperty, Mode=OneWayToSource, Converter={StaticResource blockingConverter}}"/> 
     <Button Content="Click"/> 
    </StackPanel> 
</Grid> 

注意,因为转换器有一个状态,你需要一个单独的实例每次使用资源时,我们都可以使用资源上的x:Shared="False"属性。

4

错误,当然。

如果它是一个“功能”,这是一个非常糟糕的一个...

似乎他们甚至在OneWayToSource模式的设定后添加的get()函数的调用()完成。 ..任何人都可以解释为什么?

也,感谢指出了这一点,它说明了一个问题,因为我升级我的项目.NET 4.0我曾和我不能直到现在解释...

只是一个侧面说明:我有最后通过使用依赖属性解决了这个问题。

+0

我的猜测是为了反映您在设置过程中可能应用的任何过滤,以便TextBox的内容实际上反映了“真正”设置的值。然后,OneWayToSource唯一不同的地方是它只会在应用set()之后调用get(),而不是在发送属性更改通知时调用get()。 – 2011-02-02 15:46:40

+0

在一个侧面说明中,一个以这种方式行为的属性(它暴露了一个getter,但get与设置的内容完全无关)是一个相当的病态属性。这听起来像你真正想要的是一个方法,但是打包为一个属性以允许绑定系统触发该呼叫。这可能是值得研究创建一个自定义行为,因为这样你就不必滥用财产制度。 – 2011-02-02 15:51:28

+0

@丹·布莱恩特:你在评论戴维的回答还是你在回答这个问题? :)我应该补充说,如果你删除了getter,那么每当`LostFocus`被引发时,`TextBox`都会一直是空白的。当然,这不可能是“OneWayToSource”绑定的理想方式,或者您认为如何? – 2011-02-02 17:04:29

6

这确实是由设计。通常情况下,它不应该制造麻烦,但是我的意思是,你的财产执行至少是非常规的。吸气和吸气(吸气)应该不会比得到和设置多得多,而且每个吸气和吸气应该与最后一组相一致。 (对不起,没有这方面的资料,这正是我所在的所有开发团队所称的良好公民身份)。

在此处详细了解功能的详细信息:http://karlshifflett.wordpress.com/2009/05/27/wpf-4-0-data-binding-change-great-feature/

0

这是.NET 4.0中OneWayToSource绑定的期望行为吗?

是的。这是为了让开发人员能够在不笨拙的转换器的情况下改变提供的值。

它在3.5中的工作方式有什么问题?

没问题。它在3.5中的工作方式不允许更正提供的值。

在什么情况下这种新行为更好?

当您需要更正提供的值。如果你不需要它,那么你应该写出正确的属性的getter和setter。

public string TextProperty 
{ 
    get; 
    set; 
} 

然而,我所看到的,不断变化的UpdateSourceTrigger为“的PropertyChanged”保留被重读值(这样你就可以离开旧财产申报):

<StackPanel> 
    <TextBox Text="{Binding TextProperty, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"/> 
    <Button/> 
</StackPanel> 

    private string m_textProperty; 
    public string TextProperty 
    { 
     get 
     { 
      return "Should not be used in OneWayToSource Binding"; 
     } 
     set 
     { 
      m_textProperty = value; 
     } 
    } 
2

这是很清楚的错误。似乎至少有人报告过一次。 https://connect.microsoft.com/VisualStudio/feedback/details/612444/onewaytosource-broken-in-net-4-0

我与许多其他人的同意,一个方法应该是单向的时期。

我的情况是复杂的和框架版本之间的变化具有一定功能给我带来了真正的头痛。

我有绑定到一个属性文本框。我有一个转换器,可以随时更改格式。 EG:我在文本框中输入EU5,属性获得EU005。我有绑定设置触发属性更改,因为我需要在ViewModel内查找用户类型。当我输入时,新的实现改变了文本框的值。所以如果我想输入EU512,我不能轻易地改变文本框的内容。

我已经尝试了许多事情 - 显式绑定(您决定何时更新和以何种方式。)这有同样的问题。如果我说的是UpdateSource,那么它也会重新读取该属性并更改目标。

我试过OneWayToSource并有同样的问题。我发现没有办法解决这个问题,而不会对我的虚拟机进行恼人的更改。唯一的另一种方式是删除绑定在这个领域,并开始射击事件将是可怕的。

如果MS使绑定的行为按照逻辑命名,那么我的问题就会消失。即使是绑定选项退出.net4实现并且表现为3.5的属性也适用于我。

任何人对我有什么建议可以解决这个问题?

0

我有一个双向绑定这个问题的变化。我意识到这与所讨论的问题不完全相同,但是这个答案在搜索时出现了,并且导致了我的解决方案。希望有人发现它有帮助。

我的解决方案阻止重新读取支持属性,但会更新UI时,由其他来源更改。我在Rick Sladkey的答案中将我的解决方案基于阻塞转换器。

它只是将一个检查添加到转换,以查看lastValue字段是否将转换为相同的后备存储值。如果不是,则后备存储值必须从其他源更改,并且应更新UI。

public class MyConverter : IValueConverter 
{ 
    public object lastValue; 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (LastValue != null && MyConvertBack(LastValue).Equals(value)) 
      return lastValue; 
     else 
      return MyConvert(value); 

    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     lastValue = value; 
     return MyConvertBack(value); 
    } 

    private object MyConvertBack(Object value) 
    { 
     //Conversion Code Here 
    } 

    private object MyConvert(Object value) 
    { 
     //Conversion Code Here 
    } 
} 

在我的这个特殊的用例中,我有一个长度和尺寸后缀存储在一个文本框(10米,100毫米等)。转换器将其解析为double值或添加后缀(取决于转换方向)。如果没有转换器,它会在文本框的每次更新中添加一个后缀。尝试键入'10'会导致'1m0',因为转换器会在第一次击键后运行。

相关问题