wpf:从视图模型中更改依赖项属性的值

问题描述:

我有一个自定义的用户控件,其中包含一个类型为字符串的自定义依赖项属性。应结合双向的文本框,这是一个周围的应用,如:wpf:从视图模型中更改依赖项属性的值

<Textbox Name="TextBoxInHostApp"/> 
<ctrl:MyControl 
    .... 
     MyString = "{Binding ElementName=TextBoxInHostApp, Path=Text, Mode=TwoWay}" 
</ctrl:MyControl> 

问题:

控制应该具备的功能,揭示了依赖属性也值了!

在MyControl中,我有一个简单的字符串属性“Name”,它应该更新MyString的dependeny属性值。

所以通常情况下,如果MyString的是没有绑定到外面的世界,你会在XAML使用控制,其中代码:

<Textbox Name="TextBoxInHostApp"/> 
<ctrl:MyControl 
    .... 
     MyString = "{Binding Name}" 
</ctrl:MyControl> 

但是,这不是可以在我的情况。

尝试1: 我使用的用户控件XAML内触发:

<UserControl.Style> 
    <Style> 
     <Style.Setters> 
      <Setter Property="local:MyControl.MyString" Value="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/> 
     </Style.Setters> 
    </Style> 

现在这个触发器不起作用,因为DP的“本地值”已被设置在这里:

MyString = "{Binding ... 

如果我注释掉:

<!--<MyString = "{Binding ... 

...触发正常工作,因为“L ocal值“未设置。

下一个尝试: 我尝试在MyControls视图模型硬盘的方式和代码:

public string Name 
{ 
    get 
    { 
     return _name; 
    } 
    set 
    { 
     _name = value; 
     RaisePropertyChanged("Name"); 

     MyOwningUICtrl.SetValue(MyControl.MyStringProperty, value); // ?? 
    } 
} 

我必须通过的DependencyObject调用的SetValue,这是不愉快的MVVM。这种情况必须有更好的解决方案吗?

这是由设计

每WPF的Dependency Property Precedence List,价值观当地指定的<Tag>内将始终优先于一个StyleTrigger

一个共同的问题规定值的设定值在<Tag>,然后试图改变它在Style.Trigger。解决的办法是设置默认值作为<Style>,而不是在一个<Tag><Setter>,那么这将使触发值优先于样式值

<Style> 
    <!-- Default Value 
    <Setter Property="local:MyControl.MyString" 
      Value="{Binding ElementName=TextBoxInHostApp, Path=Text, Mode=TwoWay}"/> 

    <Style.Triggers> 
     <Trigger ...> 
      <!-- Triggered Value --> 
      <Setter Property="local:MyControl.MyString" 
        Value="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/> 
     </Trigger> 
    </Style.Setters> 
</Style> 

但我没有真正看到一个触发器在你的帖子中定义的任何地方,所以我不确定这是否是你的问题。

我对代码的确切结构有点不清楚,但请记住,依赖属性有点像指向另一个值的指针。您可以将其设置为指向TextBox.Text,或指向DataContext.Name,但不能同时指向两者。

如果你想设置两个TextBox.TextMyUserControl.MyString指向DataContext.Name,那么你就应该既属性绑定到"{Binding Name}"Natxo suggests

或者,如果你想,如果在<ctrl:MyControl ...>标签没有指定MyString是绑定MyStringUserControl.Name,那么你可以尝试使用PriorityBinding(例如here),或者只是暴露Name属性外界要让外部因素使用控制如<ctrl:MyControl Name="{Binding ...}" />

+0

1st)您的权利,我使用的是样式设置器,而不是触发器2)textbox.text应该是绑定到MyString dp的属性,设计的实际情况是,dp的值可以通过两种方式进行更改:从应用程序布局上的文本框和自定义控件中的文本框中进行更改 – deafjeff 2013-03-25 15:21:29

+0

非智能解决方案我刚测试:MyOwningUICtrl.SetValue(MyControl.MyStringProperty,value); // ?? ...工作正常,但它不是很好的编程我认为 – deafjeff 2013-03-25 15:23:46

+1

@deafjeff请记住,绑定就像指针 - 它们指向一个值在'DataContext'中,听起来像y ou希望你的'MyString'依赖属性指向'UserControl'之外的某个值(比如'{Binding Name}',并且你希望'TextBox.Text'指向'UserControl.MyString'。所以你的最终结果是''和'''' – Rachel 2013-03-25 15:39:14

如果在Textbox和Mycontrol中都显示相同的值...为什么不把它们绑定到该属性? :

<Textbox Name="TextBoxInHostApp" Text="{Binding Name}"/> 
<ctrl:MyControl 
    .... 
     MyString="{Binding Name}" 
</ctrl:MyControl> 
+0

这一点是应用程序无法访问“名称”属性。由文本框表示的应用程序字符串应该通过“MyString”dp修改usercontrols,“名称”设置在“MyString”内 - ChangedCallback在这里不相关。事情是“Name”允许修改“ MyString“dp等,如果控件内部的”Name“发生变化,应用程序文本框中的文本也会发生变化 – deafjeff 2013-03-25 15:02:13