将 WPF UserControl 中的内容绑定到其属性的不同方式的优点/缺点是什么? [英] What are the advantages/disadvantages of the different ways of binding content in a WPF UserControl to its properties?

查看:22
本文介绍了将 WPF UserControl 中的内容绑定到其属性的不同方式的优点/缺点是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

When starting to work with WPF UserControls, I stumbled upon several ways to bind content of a UserControl to one of its properties.

Here's example C# code for my control:

 public sealed partial class MyUserControl : UserControl
 {
    public MyUserControl()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty TheTextProperty =
        DependencyProperty.Register("TheText",
                                    typeof (string),
                                    typeof(MyUserControl),
                                    new FrameworkPropertyMetadata(0, 
                                        FrameworkPropertyMetadataOptions.
                                             BindsTwoWayByDefault)
            );

    public string TheText
    {
        get { return (string)GetValue(TheTextProperty); }
        set { SetValue(TheTextProperty, value); }
    }
}

And here are the different ways I found to bind content to this property:

Content uses binding with RelativeSource/AncestorType

<UserControl x:Class="MyUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
    <StackPanel>
        <TextBox Text="{Binding TheText,
                        RelativeSource={RelativeSource
                                        AncestorType={x:Type UserControl}}}" />
    </StackPanel>
</UserControl>

DataContext of visual tree root is set to UserControl in XAML

<UserControl x:Class="MyUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
    <StackPanel DataContext="{Binding
                              RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}">
        <TextBox Text="{Binding TheText}" />
    </StackPanel>
</UserControl>

DataContext of visual tree root is set to UserControl in constructor

<UserControl x:Class="MyUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
    <StackPanel x:Name="VisualTreeRoot">
        <TextBox Text="{Binding TheText}" />
    </StackPanel>
</UserControl>

Here's the constructor:

    public MyUserControl()
    {
        InitializeComponent();
        VisualTreeRoot.DataContext = this;
    }

Last but not least: A warning for other people new to programming UserControls in WPF

The first time I wanted to bind content of a UserControl to one of its properties, I though "hey, let's just set the DataContext of the UserControl directly to itself":

<UserControl x:Class="MyUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">

Or:

    public MyUserControl()
    {
        InitializeComponent();
        this.DataContext = this;
    }

However, this does not work if a user of the UserControl wants to bind its properties to other binding sources. The UserControl needs to inherit the DataContext from its parent to make this work. By overwriting it as presented above, the bindings won't find their sources anymore.


My final questions:

  • What are the advantages and disadvantages of each of the presented methods?
  • When should you use which method?
  • Are there more methods?

解决方案

  • Well in the first case there is no DataContext for the TextBox set to any of it's Parent's. Hence you're having to tell the TextBox where in the VisualTree is the control with that property directly on it.
  • Second case DataContext is set on StackPanel which the TextBox inherit's accordingly. This is better than approach one if you have multiple control's in the StackPanel
  • Setting DataContext on the UserControl itself is not always wrong(via constructor or xaml). I say this because if you have 20 control's out of which 15 that need to use properties defined in it's current UserControl class and 5 that need's the parent of the UserControl's DataContext, You can always use a RelativeSource FindAncestor binding on the minority.

Only "method" I can think of that can show pt3 I mentioned is something like

<!--  Can change type to another userControl too and specify Ancestorlevel  -->
<TextBlock Text="{Binding TheText, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />

^^ This will work fine even if the TextBlock's parent UserControl has itself as it's DataContext

As far as when to use what.

That's just a logical choice, if you have multiple siblings needing the same DataContext, Setting DataContext to their parent is the right answer. I always tend to set DataContext on the Top-most element possible and if any one or two items need variations bind them out accordingly.

If in MVVM, your VM become the DataContext almost always of the Top level item of the View. everything else Bind's directly to the element whose property they need pretty much.

这篇关于将 WPF UserControl 中的内容绑定到其属性的不同方式的优点/缺点是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆