简体   繁体   中英

WPF: DependencyProperty works on TextBlock but not on custom control

Edit: a sample project can be found here .

I am using a ListBox inside my main window, which I later bind to an ObservableCollection . I use both a TextBlock and a custom control which I bind to the same property of the collection. My problem is that the TextBlock gets properly updated, whereas the custom control doesn't (it gets default constructed but its Text property is never updated by the binding).

<ListBox Name="MyCustomItemList">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding ItemText}"/>
                <local:MyCustomBlock Text="{Binding ItemText}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

I implemented MyCustomBlock as a child of System.Windows.Controls.Canvas with a Text dependency property:

public class MyCustomBlock : Canvas
{
    public MyCustomBlock() => Text = "<default>";
    public MyCustomBlock(string text) => Text = text;

    private static void TextChangedCallback(DependencyObject o,
                                            DependencyPropertyChangedEventArgs e)
    {
        ...
    }

    public string Text
    {
        get => (string)GetValue(TextProperty);
        set => SetValue(TextProperty, value);
    }

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register(
              nameof(Text), typeof(string), typeof(MyCustomBlock),
              new FrameworkPropertyMetadata("", TextChangedCallback));
}

Finally, this is the data I bind to the ListBox in the MainWindow constructor:

public class MyCustomItem
{
    public MyCustomItem(string text) => ItemText = text;
    public string ItemText { get; set; }
}

public MainWindow()
{
    InitializeComponent();

    var list = new ObservableCollection<MyCustomItem>();
    list.Add(new MyCustomItem("Hello"));
    list.Add(new MyCustomItem("World"));
    MyCustomItemList.ItemsSource = list;
}

Did I forget something in my setup? How come TextBlock.Text is seemingly properly updated but not MyCustomBlock.Text ?

Dependency properties can get their value from several sources and so WPF employs a precedence system to determine which value applies. "Local" values (provided using SetValue or SetBinding ) will override anything provided by the creating template.

In your case, your setting a "local" value in the constructor (presumably intending it to behave as a default value). A better way to set a default value is by providing it in the PropertyMetadata.

public static readonly DependencyProperty TextProperty =
    DependencyProperty.Register(
          nameof(Text), typeof(string), typeof(MyCustomBlock),
          new FrameworkPropertyMetadata("<default>", TextChangedCallback));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM