【问题标题】:WPF own UserControl with ItemsSource PropertyWPF 拥有具有 ItemsSource 属性的 UserControl
【发布时间】:2013-02-26 07:59:35
【问题描述】:

我想用 ItemsSource 属性创建一个自己的用户控件。 我创建了一个用户控件“myContainer”,并创建了一个用户控件“myItem”。现在我想在 myContainer 控件中显示 myItem 控件。所以我在 myContainer 控件中声明了一个依赖属性 ItemsSource。 但是,如果我启动一个 testproject 并将一个集合绑定到 itemssource 属性,则什么也没有发生。这是实现 itemssource 属性的正确方法吗?

Xaml: myContainer

<UserControl x:Class="Control.myContainer"
         ...
         x:Name="myUserControl">
<Grid>
    <DockPanel x:Name="myDockPanel">

    </DockPanel>
</Grid>

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

<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));
        }
    }
}

【问题讨论】:

  • 从 ListBox 或 ItemsControl 派生并将 ItemsPanel 属性设置为 DockPanel 会容易得多。通过覆盖GetContainerForItemOverride,您可以创建自己的项目类型。
  • @Clemens 我认为这是问题的答案,而不是评论
  • 你能给我举个例子吗?
  • 从您的代码中很难说出您将要实现的具体目标。我猜您的项目应显示标题文本和其他一些内容(无论是什么)。你能提供更多关于你想要什么的信息吗?您的项目类型是什么?如何可视化?
  • 你应该知道这篇文章:Data Templating Overview.

标签: wpf xaml user-controls itemssource


【解决方案1】:

您的项目类型似乎基本上如下所示:

public class DataItem
{
    public string Header { get; set; }
    public object Content { get; set; }
}

您可以通过带有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>

您当然可以在 DataTemplate 中使用您专门的 UserControl:

<DataTemplate>
    <Border BorderThickness="3" BorderBrush="Aqua">
        <StackPanel Margin="10">
            <TextBlock Text="{Binding Header}"/>
            <local:MyItemControl Content="{Binding Content}"/>
        </StackPanel>
    </Border>
</DataTemplate>

ListBox 使用的默认面板是 VirtualizingStackPanel。如果您想改用 DockPanel,可以通过设置 ItemsPanel 属性来实现:

<ListBox ItemsSource="{Binding DataItems}">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <DockPanel />
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    ...
</ListBox>

编辑:除了使用 DataTemplate,您还可以通过在 ItemsContainerStyle 中的 Style 中替换其 ControlTemplate 来完全替换 ListBoxItem 的视觉外观:

<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>

【讨论】:

  • 有没有办法在列表框项目中显示用户控件?我这样做但是当我单击用户控件中的按钮时,例如仅选择了 listboxitem
  • 你可以设置ItemContainerStyle而不是ItemTemplate。
  • 我只找到了一种设置 ListBoxItem 样式的方法,但我不能使用用户控件中的对象:/
  • 我的意思是在样式设置器中设置 ListBoxItem 的 ControlTemplate。查看我的编辑。
  • 我完全按照您的示例进行操作,并且列表框项显示正确,但我无法访问通过绑定加载到 contentpresenter 中的用户控件中的对象(按钮)。我看到按钮但无法点击它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-16
  • 2019-12-08
  • 1970-01-01
  • 2022-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多