OneWayToSource绑定似乎在.NET 4.0中被破坏
OneWayToSource
绑定似乎在.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
input的任何文本
在.NET 4.0中 ,如果我在TextBox
键入一些文本,然后按下Tab使其失去焦点,则TextBox
将恢复为TextProperty
的值(意思是“不应在OneWayToSource绑定中使用” )。 这是重新阅读旨在.NET 4.0中的OneWayToSource
绑定? 我只是希望TextBox
将其值推入TextProperty
而不是其他方式。
更新
在这个问题上增加一个赏金,因为这已经成为市长在我的项目中带来的不便,我想知道这个变化的原因。 看起来绑定更新源后调用get
。 这是在.NET 4.0中的OneWayToSource
绑定所需的行为?
如是
- 它在3.5中的工作方式有什么问题?
- 这种新行为在哪些情况下更好?
或者这实际上是一个我们希望在未来版本中修复的错误?
Karl Shifflett的博客和@ Simpzon的答案已经涵盖了为什么他们添加了这个function,为什么它不是一个总是得到设定的属性的问题。 在你自己的代码中,你总是使用一个具有合适的语义进行绑定的中间属性,并使用一个具有你想要的语义的内部属性。 我会调用中间属性一个“阻塞”属性,因为它阻止到达你的内部属性的获取。
但是,如果您无法访问要设置属性的实体的源代码,并且想要旧的行为,则可以使用转换器。
这是一个阻塞转换器的状态:
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"
属性。
这确实是由devise。 通常情况下,这不应该造成麻烦,但是我的意思是,你的财产执行至less是非常规的。 Getters和Setter(访问器)实际上不应该比get和set更多,而且每个get都应该与最后一个对应的set一致。 (对不起,没有这个资源,这就是我所在的所有开发团队所称的优秀公民身份)。
有关这个function的更多细节在这里: http : //karlshifflett.wordpress.com/2009/05/27/wpf-4-0-data-binding-change-great-feature/
错误,绝对。
如果这是一个“function”,这是一个非常糟糕的…
看来他们在set()完成之后添加了对get()函数的调用,即使是在OneWayToSource模式下…任何人都可以解释为什么?
此外,感谢您指出这一点,它解释了我已经有了一个问题,因为我升级我的项目到.net 4.0,我不能解释,直到现在…
只是一个侧面说明:我已经通过在最后使用依赖属性解决了这个问题。
这很明显是一个错误。 似乎至less有一次有人报告过。 https://connect.microsoft.com/VisualStudio/feedback/details/612444/onewaytosource-broken-in-net-4-0
我同意其他许多人的观点,即一种方式应该是单向的。
我的情况是复杂的,并且在框架版本之间改变了function,这使我非常头疼。
我有一个文本框绑定到一个属性。 我有一个转换器,即时更改格式。 EG:我在文本框中inputEU5,属性获得EU005。 我有绑定设置触发属性更改,因为我需要在ViewModel内查找用户types。 新的实现改变了我input的文本框的值。 所以如果我想inputEU512,我不能轻易地改变文本框的内容。
我已经尝试了很多东西 – 显式绑定(你决定什么时候更新和哪种方式)。这有同样的问题。 如果我说,UpdateSource,它也会重新读取属性并更改目标。
我试过OneWayToSource,并有同样的问题。 我发现没有办法解决这个问题,而不会对我的虚拟机进行恼人的更改。 唯一的另一种方法是删除绑定在这个领域,并开始射击事件将是可怕的。
如果MS使绑定的行为,因为它是逻辑命名,那么我的问题就会消失。 即使是绑定的属性,select退出.net4实现,并performance为3.5将适用于我。
任何人对我如何解决这个问题有任何build议?
我有一个双向约束这个问题的变化。 我意识到,这是不完全相同的问题正在讨论,但这个答案在search时达到顶峰,并导致我的解决scheme。 希望有人发现它有帮助。
我的解决scheme阻止重新读取后台属性,但会更新用户界面时,由其他来源更改。 我在Rick Sladkey的答案中将我的解决scheme放在了阻塞转换器上。
它只是添加一个检查到转换,看是否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毫米等)。 转换器将其parsing为double值或添加后缀(取决于转换的方向)。 没有转换器,它会在文本框的每个更新上添加一个后缀。 尝试input“10”将导致“1m0”,因为转换器将在第一次击键后运行。
这是在.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; } }