【问题标题】:UserControl DependencyProperty binding in ListViewListView 中的 UserControl DependencyProperty 绑定
【发布时间】:2016-05-13 19:47:58
【问题描述】:

当我尝试在 ListView 中使用自定义 UserControl 时,它会失败并且只显示空块(以下 TextBlock 可以工作)。虽然 ListView 之外的 customControl 工作得很好。有什么问题?


MainWindow.xaml

<Grid>
    <StackPanel>
        <controls:CustomControl x:Name="customControl" CustomText="Test"/>
        <ListView x:Name="listView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <controls:CustomControl CustomObject="{Binding}"/>
                        <TextBlock Text="{Binding Text}"/>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackPanel>
</Grid>

MainWindow.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        InitializeMyComponent();
    }

    public System.Collections.ObjectModel.ObservableCollection<CustomClass> CustomCollection { get; set; }

    private void InitializeMyComponent()
    {
        this.CustomCollection = new System.Collections.ObjectModel.ObservableCollection<CustomClass>();
        this.CustomCollection.Add(new CustomClass() { Number = 1, Text = "a" });
        this.CustomCollection.Add(new CustomClass() { Number = 2, Text = "b" });
        this.CustomCollection.Add(new CustomClass() { Number = 3, Text = "c" });
        this.listView.ItemsSource = this.CustomCollection;
        this.customControl.Custom = new CustomClass() { Number = 0, Text = "customControl" };
    }
}

CustomControl.xaml

<Grid>
    <StackPanel>
        <TextBlock>
            <Run x:Name="numberRun" Text="{Binding CustomObject.Number}"/>
            <Run x:Name="textRun" Text="{Binding CustomObject.Text}"/>
            <Run Text="{Binding CustomText}"/>
        </TextBlock>
    </StackPanel>
</Grid>

CustomControl.cs

public partial class CustomControl : UserControl
{
    public static readonly DependencyProperty CustomObjectProperty;
    public static readonly DependencyProperty CustomTextProperty;

    static CustomControl()
    {
        CustomObjectProperty = DependencyProperty.Register("CustomObject", typeof(CustomClass), typeof(CustomControl), new PropertyMetadata(default(CustomClass), OnCustomObjectPropertyChanged));
        CustomTextProperty = DependencyProperty.Register("CustomText", typeof(string), typeof(CustomControl), new PropertyMetadata(string.Empty, OnCustomTextPropertyChanged));
    }
    public CustomControl()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    public CustomClass CustomObject
    {
        get
        {
            return (CustomClass)(this.GetValue(CustomObjectProperty));
        }
        set
        {
            this.SetValue(CustomObjectProperty, value);
        }
    }
    public string CustomText
    {
        get
        {
            return (string)(this.GetValue(CustomTextProperty));
        }
        set
        {
            this.SetValue(CustomTextProperty, value);
        }
    }

    private static void OnCustomObjectPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { }
    private static void OnCustomTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { }
}

CustomClass.cs

public class CustomClass : INotifyPropertyChanged
{
    private int number;
    private string text;

    public CustomClass()
    {
        this.number = new int();
        this.text = string.Empty;
    }

    public int Number
    {
        get
        {
            return this.number;
        }
        set
        {
            this.number = value;
            this.OnPropertyChanged();
        }
    }
    public string Text
    {
        get
        {
            return this.text;
        }
        set
        {
            this.text = value;
            this.OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string name = null)
    {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

【问题讨论】:

    标签: c# wpf listview user-controls dependency-properties


    【解决方案1】:

    将 UserControl 的 DataContext 设置为 UserControl 实例,例如

    this.DataContext = this;
    

    有效地防止绑定到“外部”继承的 DataContext,正如预期的那样

    <controls:CustomControl CustomObject="{Binding}"/>
    

    作为一般规则,从不显式设置 UserControl 的 DataContext。从 UserControl 的构造函数中删除上述行,并在 UserControl 的 XAML 中使用 RelativeSource 编写绑定:

    <Run x:Name="numberRun" Text="{Binding CustomObject.Number,
        RelativeSource={RelativeSource AncestorType=UserControl}}"/>
    

    【讨论】:

    • 感谢您的帮助。真的行!我还有很多东西要学。
    • 别担心。这是 WPF 用户控件最常犯的错误之一。
    猜你喜欢
    • 1970-01-01
    • 2012-06-06
    • 2013-06-03
    • 2014-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-09
    相关资源
    最近更新 更多