用户控件的DependencyProperty在ListView的结合 [英] UserControl DependencyProperty binding in ListView
问题描述
当我尝试在ListView使用自定义用户控件,它失败,只有空块显示(以下TextBlock的工作虽然)。而在ListView外customControl工作pretty好。有什么问题?
MainWindow.xaml
<网格和GT;
<&StackPanel的GT;
<控制:CustomControl X:NAME =customControlCustomText =测试/>
< ListView的X:名称=ListView控件>
< ListView.ItemTemplate>
<&DataTemplate的GT;
<&StackPanel的GT;
<控制:CustomControl CustomObject ={结合}/>
< TextBlock的文本={结合文字}/>
< / StackPanel的>
< / DataTemplate中>
< /ListView.ItemTemplate>
< /&的ListView GT;
< / StackPanel的>
< /网格和GT;
MainWindow.cs
公共部分类主窗口:窗口
{
公共主窗口()
{
的InitializeComponent();
InitializeMyComponent();
} 公共System.Collections.ObjectModel.ObservableCollection< CustomClass> CustomCollection的{搞定;组; } 私人无效InitializeMyComponent()
{
this.CustomCollection =新System.Collections.ObjectModel.ObservableCollection< CustomClass>();
this.CustomCollection.Add(新CustomClass(){总数= 1,文本=A});
this.CustomCollection.Add(新CustomClass(){总数= 2,文本=B});
this.CustomCollection.Add(新CustomClass(){总数= 3,文本=C});
this.listView.ItemsSource = this.CustomCollection;
this.customControl.Custom =新CustomClass(){数= 0,文本=customControl};
}
}
CustomControl.xaml
<网格和GT;
<&StackPanel的GT;
<&的TextBlock GT;
<运行X:NAME =numberRun文本={结合CustomObject.Number}/>
<运行X:NAME =textRun文本={结合CustomObject.Text}/>
<运行文本={结合CustomText}/>
< / TextBlock的>
< / StackPanel的>
< /网格和GT;
CustomControl.cs
公共部分类CustomControl:用户控件
{
公共静态只读的DependencyProperty CustomObjectProperty;
公共静态只读的DependencyProperty CustomTextProperty; 静态CustomControl()
{
CustomObjectProperty = DependencyProperty.Register(CustomObject的typeof(CustomClass)的typeof(CustomControl),新PropertyMetadata(默认值(CustomClass),OnCustomObjectPropertyChanged));
CustomTextProperty = DependencyProperty.Register(CustomText的typeof(串)的typeof(CustomControl),新PropertyMetadata(的String.Empty,OnCustomTextPropertyChanged));
}
公共CustomControl()
{
的InitializeComponent();
this.DataContext =这一点;
} 公共CustomClass CustomObject
{
得到
{
回报(CustomClass)(this.GetValue(CustomObjectProperty));
}
组
{
this.SetValue(CustomObjectProperty,值);
}
}
公共字符串CustomText
{
得到
{
回报(字符串)(this.GetValue(CustomTextProperty));
}
组
{
this.SetValue(CustomTextProperty,值);
}
} 私有静态无效OnCustomObjectPropertyChanged(DependencyObject的D,DependencyPropertyChangedEventArgs E){}
私有静态无效OnCustomTextPropertyChanged(DependencyObject的D,DependencyPropertyChangedEventArgs E){}
}
CustomClass.cs
公共类CustomClass:INotifyPropertyChanged的
{
私人诠释数目;
私人字符串文本; 公共CustomClass()
{
this.number = INT新();
this.text =的String.Empty;
} 公众诠释号码
{
得到
{
返回this.number;
}
组
{
this.number =价值;
this.OnPropertyChanged();
}
}
公共字符串文本
{
得到
{
返回this.text;
}
组
{
this.text =价值;
this.OnPropertyChanged();
}
} 公共事件PropertyChangedEventHandler的PropertyChanged; 保护无效OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName]字符串名称= NULL)
{
PropertyChangedEventHandler处理器= this.PropertyChanged;
如果(处理!= NULL)
{
处理器(这一点,新PropertyChangedEventArgs(名));
}
}
}
设置用户控件的的DataContext
像
this.DataContext =这一点;
有效prevents绑定外部,继承的DataContext,如预期在
<控制:CustomControl CustomObject ={结合}/>
作为一般规则,的从不的设置用户控件的DataContext的明确。在该用户的XAML与的RelativeSource取下用户控件的构造上面一行,并写入绑定:
<运行X:NAME =numberRun文本={结合CustomObject.Number,
的RelativeSource = {的RelativeSource AncestorType =用户控件}}/>
When I try to use a custom UserControl in a ListView, it fails and only empty blocks are displayed (the following TextBlock works though). While the customControl outside the ListView works pretty well. What's the problem?
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));
}
}
}
Setting a UserControl's DataContext
to the UserControl instance like
this.DataContext = this;
effectively prevents bindings to an "external", inherited DataContext, as expected in
<controls:CustomControl CustomObject="{Binding}"/>
As a general rule, never set a UserControl's DataContext explicitly. Remove the above line from the UserControl's constructor, and write the bindings in the UserControl's XAML with RelativeSource:
<Run x:Name="numberRun" Text="{Binding CustomObject.Number,
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
这篇关于用户控件的DependencyProperty在ListView的结合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!