c# - custom - wpf usercontrol教學



WPF UserControl不會繼承父級的DataContext (1)

UserControl實際上是從其父元素繼承DataContext。 然而,DataContext中沒有TextFromParent屬性(因為它是MainWindow實例)。

UserControl的XAML中的綁定應該綁定到UserControl本身的一個屬性,而不是當前的DataContext。 因此,它必須使用UserControl實例作為源對象:

<TextBlock Text="{Binding TextFromParent,
                  RelativeSource={RelativeSource AncestorType=UserControl}}" />

將UserControl的DataContext設置為自身不是一個選項,因為它可以防止DataContext值從控件的父元素繼承。

但是,您可以在UserControl的XAML中設置根元素的DataContext,以避免在潛在的多個Bindings上設置RelativeSource:

<UserControl ...>
    <Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
        <TextBlock Text="{Binding TextFromParent}" />
    </Grid>
</UserControl>

我試圖開發一個可重用的用戶控件,但遇到綁定的問題。 我創建了一個較小的應用程序來測試它,但無法將其整理出來,或者至少理解為什麼它不能正常工作。

代碼如下。 我所期望的是我放在MainWindow.xaml上的TestUserControl的實例將繼承DataContext,就像它的TextBlock一樣。 相反,它的DataContext似乎是空的。 DataContext沒有傳遞的原因嗎? 我必須自動設置嗎?

MainWindow.xaml

<Window x:Class="WpfTestApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfTestApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel Orientation="Vertical">
        <local:TestUserControl TextFromParent="{Binding SomeText}" />
        <TextBlock Name="TestTextBlock" Text="{Binding SomeText}" />

    </StackPanel>
</Window>

MainWindow.xaml.cs

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;

namespace WpfTestApp
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private string _someText;

        public MainWindow()
        {
            DataContext = this;

            InitializeComponent();

            SomeText = "New Text!";
        }

        public string SomeText
        {
            get { return _someText; }
            set
            {
                _someText = value;
                NotifyOnPropertyChanged();
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;

        protected void NotifyOnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

TestUserControl.xaml

<UserControl x:Class="WpfTestApp.TestUserControl"
             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" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfTestApp"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <TextBlock Name="TheTextBlock" Text="{Binding TextFromParent}" />

    </Grid>
</UserControl>

TestUserControl.xaml.cs

using System.Windows;
using System.Windows.Controls;

namespace WpfTestApp
{
    public partial class TestUserControl : UserControl
    {
        public TestUserControl()
        {
            InitializeComponent();
        }

        public string TextFromParent
        {
            get { return (string)GetValue(TextFromParentProperty); }
            set { SetValue(TextFromParentProperty, value); }
        }

        public static readonly DependencyProperty TextFromParentProperty = DependencyProperty.Register(
            "TextFromParent", typeof(string), typeof(TestUserControl), new PropertyMetadata());
    }
}

運行時程序看起來像下面的樣子,第一個文本是空白的,然後是帶有工作綁定的TextBlock:





user-controls