簡體   English   中英

如何通過綁定在 WPF UserControl 中引用自定義屬性值?

[英]How do I reference a custom property value in a WPF UserControl via Binding?

我正在使用自定義 UserControl 構建 WPF 應用程序,並且我正在嘗試了解屬性綁定應該如何工作。 我連最基本的綁定都無法工作,而且它很簡單,可以提煉成一個小例子,所以我認為有更多 WPF 經驗的人可能能讓我走上正軌。

我定義了一個名為TestControl的自定義 UserControl ,它公開了一個Foo屬性,該屬性旨在在放置 UserControl 時在 XAML 中設置。

測試控件.xaml.cs

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

namespace BindingTest
{
    public partial class TestControl : UserControl
    {
        public static readonly DependencyProperty FooProperty = DependencyProperty.Register("Foo", typeof(string), typeof(TestControl));
        public string Foo
        {
            get { return (string)GetValue(FooProperty); }
            set { SetValue(FooProperty, value); }
        }

        public TestControl()
        {
            InitializeComponent();
        }
    }
}

TestControl 的標記只是將其定義為具有單個按鈕的控件,其標簽文本顯示 Foo 屬性的當前值:

測試控件.xaml

<UserControl x:Class="BindingTest.TestControl"
             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:BindingTest"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Button Content="{Binding Foo}" />
    </Grid>
</UserControl>

在我的MainWindow類中,我只放置了一個 TestControl 實例,其 Foo 屬性設置為“Hello”。

主窗口.xaml

<Window x:Class="BindingTest.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:BindingTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <local:TestControl Foo="Hello" />
    </Grid>
</Window>

我希望當我構建和啟動這個應用程序時,我會看到一個帶有一個按鈕的窗口,上面寫着“你好”。 但是,按鈕是空白的:綁定似乎不起作用。

如果我向 TestControl 的按鈕添加一個單擊處理程序,我可以驗證該值是否正在幕后更新:

// Added to TestControl.xaml.cs:
private void Button_Click(object sender, RoutedEventArgs e)
{
    Console.WriteLine("Button clicked; Foo is '{0}'", Foo);
}

// Updated in TestControl.xaml:
// <Button Content="{Binding Foo}" Click="Button_Click" />

當我點擊按鈕時,我Button clicked; Foo is 'Hello' Button clicked; Foo is 'Hello' ,但 GUI 永遠不會更新。 我試過使用Path=FooXPath=Foo等,以及設置UpdateSourceTrigger=PropertyChanged並使用NotifyOnTargetUpdated=True驗證更新......似乎沒有任何內容導致 UI 中的文本被更新以匹配底層屬性值,即使屬性值似乎更新得很好。

我究竟做錯了什么? 我覺得我如何處理這個問題只是一個簡單而根本的誤解。

編輯:

多探索一下並閱讀類似的問題讓我找到了一個潛在的解決方法:即,向 TestControl.xaml 中的根 UserControl 元素添加一個名稱( x:Name="control" ),並更改綁定以顯式指定該控件( {Binding Foo, ElementName=control} )。

我猜默認情況下,Button 元素上的{Binding Foo}僅表示“在此 Button 控件上找到名為 'Foo' 的屬性” ,而我認為它的意思是“在聲明此 Button 的上下文,即在 TestControl" 上

在這里指定一個顯式的 ElementName 是最好的解決方法嗎?

您必須將 Binding 的源對象設置為 UserControl 實例,例如:

<Button Content="{Binding Foo, RelativeSource={RelativeSource AncestorType=UserControl}}"/>

或者

<UserControl ... x:Name="theControl">
...
<Button Content="{Binding Foo, ElementName=theControl}"/>

如果您有很多這樣的綁定,您還可以將 UserControl 的 XAML 中頂級元素的 DataContext 設置為 UserControl 實例:

<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
    <Button Content="{Binding Foo}" />
    <Button Content="{Binding Bar}" />
</Grid>

但是,您必須避免設置 UserControl 的 DataContext(“專家”博主通常建議這樣做),因為這會破壞 UserControl 屬性的基於 DataContext 的綁定,例如

<local:TestControl Foo="{Binding SomeFoo}" />

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM