通过DataContext无绑定从ViewModel获取值



WPF新手。我正在创建UserControls,它们需要对ViewModel状态进行读取访问才能完成任务。我目前使用以下技术:

public partial class ControlBar : UserControl
{
    private static readonly DependencyProperty URLProperty =
        DependencyProperty.Register("URL", typeof(string), typeof(ControlBar),
        new UIPropertyMetadata(null));
    public ControlBar()
    {
        InitializeComponent();
        SetBinding(URLProperty, "CurrentPage.URL");
        Pin.Click += Pin_Click;       
    }
    private void Pin_Click(object sender, RoutedEventArgs e)
    {
        var URL = (string)GetValue(URLProperty);
    }
}

这是正确的方法吗?为我需要访问的每个变量设置一个长期绑定是否过于夸张?或者你可以做一些类似的事情:

GetValue(new Path("CurrentPage.URL..... 

很明显,以上都是我编造的。

谢谢!

通常情况下,数据绑定是可行的。但是,有时在创建具有视图特定关注点的控件时,数据绑定将不适用。

在这些情况下,您将希望能够与DependencyProperty交互以设置它,并知道它何时更改。我一直在遵循一个模式,这是我从MSDN杂志上Charles Petzold的一篇文章中学到的。

我对另一个问题的回答显示了为UserControl堆栈溢出创建DependencyProperty的模式:WPF/SilverLight 中的依赖属性

同样,数据绑定到视图模型可能会解决您的问题,但DependencyProperty可能会根据具体情况发挥作用。

回应评论的更新:

在许多情况下,您可以在不使用DependencyProperty的情况下在UserControl中数据绑定。例如,如果您有一个显示名称的TextBlock,您可以将一个TextBlock放在UserControl 的XAML中

<TextBlock Text="{Binding Path=NameString}" />

在DataContext中存在的视图模型中,您将具有属性NameString,如果TextBlock要在NameString属性更改时更新显示,则视图模型应实现INotifyPropertyChanged,并且该属性应使用随事件一起发送的属性名称激发PropertyChanged事件。

protected string _NameString;
public string NameString
{
    get { return _NameString; }
    set { _NameString = value: Notify("NameString"); }
}

其中Notify是一个方法,用于检查PropertyChanged事件是否为null,如果不是null则发送该事件。

如果要使用UserControl的所有地方都有一个具有Name属性的视图模型,则此操作效果良好。最棒的是,UserControl可以在托管它的任何地方获取DataContext,并绑定到外部视图模型。

当您想开始将同一个UserControl绑定到不同的属性时,您可能需要使用DependencyProperty。在这种情况下,您可以使用DependencyProperty创建UserControl,并将其绑定到不同的属性

<my:SampleControl NameString="{Binding Path=GivenName}" />
<my:SampleControl NameString="{Binding Path=FamilyName}" />

然后有一个内部视图模型,当绑定属性更改时,DependencyProperty更改处理程序会更新该模型。

更新:没有DependencyProperty或绑定

您总是可以向UserControl添加一个普通的C#属性,并以这种方式传递数据。

public MyClass Data { get; set; }

然后在UserControl的代码后面,您可以简单地使用属性:

if (this.Data != null)
{
    this.textBox1.Text = Data.NameString;
}

回应评论的更新:

访问代码中视图模型的另一种方法是将DataContext转换为您的视图模型类型:

MyClass data = this.DataContext as MyClass;
if (data != null)
{
    // do something
    this.textBox1.Text = data.NameString;
}

最新更新