WPF 拥有带有 ItemsSource 属性的 UserControl
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15084120/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF own UserControl with ItemsSource Property
提问by user2025830
I want to create a own Usercontrol with an ItemsSource Property. I have created a UserControl "myContainer" and i have created a UserControl "myItem". Now I want to show the myItem Controls in the myContainer Control. So I declared a dependency Property ItemsSource in the myContainer Control. But if i start a testproject and bind a collection to the itemssource property nothing happend. is that the right way to implement a itemssource property?
我想用 ItemsSource 属性创建一个自己的用户控件。我创建了一个用户控件“myContainer”,我创建了一个用户控件“myItem”。现在我想在 myContainer 控件中显示 myItem 控件。所以我在 myContainer 控件中声明了一个依赖属性 ItemsSource。但是,如果我启动一个测试项目并将集合绑定到 itemssource 属性,则什么也没有发生。这是实现 itemssource 属性的正确方法吗?
Xaml: myContainer
Xaml:我的容器
<UserControl x:Class="Control.myContainer"
...
x:Name="myUserControl">
<Grid>
<DockPanel x:Name="myDockPanel">
</DockPanel>
</Grid>
Code Behind myContainer
myContainer 背后的代码
public partial class myContainer : UserControl, INotifyPropertyChanged
{
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(myItem), typeof(myContainer));
public myContainer()
{
InitializeComponent();
DataContext = this;
}
public ObservableCollection<myItem> ItemsSource
{
get
{
return (ObservableCollection<myItem>)GetValue(ItemsSourceProperty);
}
set
{
SetValue(ItemsSourceProperty, value);
OnPropertyChanged("ItemsSource");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Xaml myItem
Xaml 我的项目
<UserControl x:Class="Control.myItem"
...
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Border BorderThickness="1" BorderBrush="Black" CornerRadius="2">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Background="LightGray">
<DockPanel Margin="2,2,2,2">
<Button x:Name="Button_Close" DockPanel.Dock="Right" Width="14" Height="14" Margin="5,0,0,0" VerticalAlignment="Center"></Button>
<Button x:Name="Button_Undock" DockPanel.Dock="Right" Width="14" Height="14" Margin="5,0,0,0" VerticalAlignment="Center"></Button>
<TextBlock DockPanel.Dock="Left" VerticalAlignment="Center" FontWeight="Bold" Text="{Binding Header,UpdateSourceTrigger=PropertyChanged}"></TextBlock>
</DockPanel>
</StackPanel>
<ContentPresenter DockPanel.Dock="Top" ContentSource="Content"></ContentPresenter>
</DockPanel>
</Border>
</Grid>
CodeBehind myItem
我的项目背后的代码
public partial class myItem : UserControl, INotifyPropertyChanged
{
public static DependencyProperty _Header =
DependencyProperty.Register("Header", typeof(String), typeof(myItem), new UIPropertyMetadata("Item"));
public myItem()
{
InitializeComponent();
DataContext = this;
}
public String Header
{
get
{
return (String)GetValue(_Header);
}
set
{
SetValue(_Header, value);
OnPropertyChanged("Header");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
回答by Clemens
It seems like you have an item type that basically looks like this:
看起来您的项目类型基本上如下所示:
public class DataItem
{
public string Header { get; set; }
public object Content { get; set; }
}
You may display items of this type by means of a ListBox with a DataTemplatefor the items, set by the ItemTemplateproperty:
您可以通过 ListBox 显示这种类型DataTemplate的项目,其中的项目由ItemTemplate属性设置:
<ListBox ItemsSource="{Binding DataItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="3" BorderBrush="Aqua">
<StackPanel Margin="10">
<TextBlock Text="{Binding Header}"/>
<ContentPresenter Content="{Binding Content}"/>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You may of course use your specialized UserControl inside the DataTemplate:
您当然可以在 DataTemplate 中使用您专门的 UserControl:
<DataTemplate>
<Border BorderThickness="3" BorderBrush="Aqua">
<StackPanel Margin="10">
<TextBlock Text="{Binding Header}"/>
<local:MyItemControl Content="{Binding Content}"/>
</StackPanel>
</Border>
</DataTemplate>
The default panel used by a ListBox is a VirtualizingStackPanel. If you want to use a DockPanel instead, you can achive that by setting the ItemsPanelproperty:
ListBox 使用的默认面板是 VirtualizingStackPanel。如果你想改用 DockPanel,你可以通过设置ItemsPanel属性来实现:
<ListBox ItemsSource="{Binding DataItems}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<DockPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
...
</ListBox>
EDIT: Instead of using a DataTemplate you may also completely replace the visual appearance of a ListBoxItem by replacing its ControlTemplate in a Style in ItemsContainerStyle:
编辑:除了使用 DataTemplate,您还可以通过在样式中替换其 ControlTemplate 来完全替换 ListBoxItem 的视觉外观ItemsContainerStyle:
<ListBox ItemsSource="{Binding DataItems}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border BorderThickness="3" BorderBrush="Aqua">
<StackPanel Margin="10">
<TextBlock Text="{Binding Header}"/>
<ContentPresenter Content="{Binding Content}"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
...
</ListBox>

