C# 使用ObservableCollection的自定义控件绑定
我有自定义控件MyGridC# 使用ObservableCollection的自定义控件绑定,c#,.net,C#,.net,我有自定义控件MyGrid public class MyGrid : Canvas { //... ObservableCollection<object> items = new ObservableCollection<object>(); public ObservableCollection<object> Items { get { return items; } set {
public class MyGrid : Canvas
{
//...
ObservableCollection<object> items = new ObservableCollection<object>();
public ObservableCollection<object> Items
{
get { return items; }
set {
items = value;
UpdateValues();
UpdateGrid();
}
}
//..
}
公共类MyGrid:Canvas
{
//...
ObservableCollection items=新的ObservableCollection();
公共可观测收集项目
{
获取{返回项;}
集合{
项目=价值;
updateValue();
UpdateGrid();
}
}
//..
}
我希望项目可以从XAML代码绑定:
<local:MyGrid Items="{Binding Numbers}" />
其中数字是ObservableCollection(这很好,我可以使用它绑定到默认控件)。
我曾尝试将项定义为DependencyProperty,但它是静态的,我需要在具有不同数据源的页面上使用多个控件,因此使用静态项将不起作用。上面的代码也不起作用。InitializeComponent()引发异常:未能分配到属性“App.MyGrid.Items”。[第27行位置:114]。我怎样才能让它工作呢?也许这会对你有所帮助
<ItemsControl ItemsSource="{Binding items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,5,5,0" VerticalAlignment="Top">
<TextBlock TextAlignment="Right" FontWeight="Bold" Text="{Binding yourVariable}" Height="16"/>
<TextBlock TextAlignment="Right" Text="{Binding yourVariable1}" FontSize="26"/>
<TextBlock TextAlignment="Right" Text="{Binding yourVariable2}" FontSize="10" Foreground="DarkGray"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer Padding="{TemplateBinding Padding}" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel>
</WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
这可能不是你真正想要的。但我认为这可以帮助您。随着MyGrid从Canvas扩展而来(Canvas也是一个DependencyObject),您可以在MyGrid中实现Dependency属性
<ItemsControl ItemsSource="{Binding items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,5,5,0" VerticalAlignment="Top">
<TextBlock TextAlignment="Right" FontWeight="Bold" Text="{Binding yourVariable}" Height="16"/>
<TextBlock TextAlignment="Right" Text="{Binding yourVariable1}" FontSize="26"/>
<TextBlock TextAlignment="Right" Text="{Binding yourVariable2}" FontSize="10" Foreground="DarkGray"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer Padding="{TemplateBinding Padding}" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel>
</WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
然后还可以使用PropertyChangedCallback
实现它,这将允许您注册/取消注册事件本身,然后您可以在其中更新网格/值
因此,您可以这样更改MyGrid:
public class MyGrid : Canvas
{
protected static PropertyChangedCallback ItemsPropertyChangedCallback = new PropertyChangedCallback(ItemsPropertyChanged);
public static DependencyProperty ItemsProperty = DependencyProperty.RegisterAttached("Items", typeof(INotifyCollectionChanged), typeof(MyGrid), new PropertyMetadata(null, ItemsPropertyChangedCallback));
private static void ItemsPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
MyGrid thisGrid = (MyGrid)sender;
if (thisGrid == null)
{
return;
}
thisGrid.UnregisterItems(e.OldValue as INotifyCollectionChanged);
thisGrid.RegisterItems(e.NewValue as INotifyCollectionChanged);
thisGrid.Refresh();
}
public INotifyCollectionChanged Items
{
get
{
return (INotifyCollectionChanged)GetValue(ItemsProperty);
}
set
{
SetValue(ItemsProperty, value);
}
}
protected void UnregisterItems(INotifyCollectionChanged items)
{
if (items == null)
{
return;
}
items.CollectionChanged -= ItemsChanged;
}
protected void RegisterItems(INotifyCollectionChanged items)
{
if (items == null)
{
return;
}
items.CollectionChanged += ItemsChanged;
}
protected virtual void UpdateValues()
{
System.Diagnostics.Debug.WriteLine("Updating values");
}
protected virtual void UpdateGrid()
{
System.Diagnostics.Debug.WriteLine("Updating grid");
}
public void Refresh()
{
UpdateValues();
UpdateGrid();
}
protected virtual void ItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
Refresh();
}
public MyGrid()
{
}
}
在Xaml中,您可以稍后绑定到Items属性。当使用另一个集合更改Items属性时,它将从上一个对象(如果有)的已更改事件中注销,然后注册到新对象(如果有)。之后,它将调用类的Refresh方法(然后调用UpdateValues/UpdateGrid方法)
我也部分同意@user3248647的观点,如果可以的话,你应该利用绑定和ContentTemplates,但是如果你不能使用它们,你可以让你的dependencProperty至少做出这样的反应
是的,DependencyProperty在类上是静态的,但是属性本身总是在类内部实现的。使用PropertyChangedCallback时,只需将发送者强制转换回“MyGrid”,然后您就可以更改实例成员:)Items集合声明为属性,但对于绑定,您需要将其声明为公共属性。希望这能帮到你:谢谢你的反馈,我发布了错误的代码,我使用的是公共财产。邮政编码updated@Icepickle我没弄错你的想法吧?编辑的代码如下:public readonly ObservableCollection items=new ObservableCollection();公共ObservableCollection项{get{return Items;}set{}}仍然不起作用。@EricTroy,没关系,我错了:D