wpf:从viewmodel更改依赖项属性的值

时间:2013-03-25 13:47:33

标签: wpf dependency-properties

我有一个自定义usercontrol,其自定义依赖项属性为string类型。它应该被绑定到文本框中,文本框位于周围的应用程序中,如下所示:

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

问题:

Control应具有显示依赖属性值的功能!

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

通常情况下,如果MyString没有绑定到外部世界,您将在使用控件的xaml中进行编码:

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

但是我的情况并不适用。

尝试1: 我在usercontrol xaml中使用了一个触发器:

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

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

MyString = "{Binding ...

如果我发表评论:

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

...触发器工作正常,因为未设置“本地值”。

下次尝试: 我在MyControls viewmodel中尝试了很难的方法和代码:

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

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

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

2 个答案:

答案 0 :(得分:3)

这是设计

根据WPF的Dependency Property Precedence List<Tag>内本地指定的值始终优先于StyleTrigger

中指定的值

常见问题是在<Tag>中设置值,然后尝试在Style.Trigger中更改它。解决方案是在<Setter>而不是<Style>中将默认值设置为<Tag>,然后允许触发值优先于样式值

<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>

但我实际上并没有在你的帖子中看到任何定义的Trigger,所以我不确定这是不是你的问题。

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

如果您要将TextBox.TextMyUserControl.MyString设置为指向DataContext.Name,则应将这两个属性绑定到"{Binding Name}",如Natxo suggests

如果您在MyString标记中未指定UserControl.Name时尝试将MyString绑定到<ctrl:MyControl ...>,则可以尝试使用PriorityBinding (示例here),或者只是将Name属性公开给外界,让外部元素使用控件,如<ctrl:MyControl Name="{Binding ...}" />

答案 1 :(得分:1)

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

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