【问题标题】:Bind ItemsControl ItemSource to UserControl Dependency Property将 ItemsControl ItemSource 绑定到 UserControl 依赖属性
【发布时间】:2018-12-06 23:35:17
【问题描述】:

这是我第一次尝试创建具有依赖属性的用户控件。所以请原谅我对这个主题缺乏了解。我在我的一个页面上创建了一个通用设计,我想将其引入可重用的用户控件。

页面上的原始控制

所以这是我试图移植到可重用 UserControl 的控件

<ToggleButton x:Name="filterButton" Background="{StaticResource BackgroundLightBrush}" BorderThickness="0">
    <fa:ImageAwesome x:Name="border"
                     Height="15"
                     Foreground="{StaticResource MediumBlueBrush}"
                     Icon="Filter"/>
</ToggleButton>

<Popup x:Name="popup" 
       AllowsTransparency="True"
       StaysOpen="False"
       PlacementTarget="{Binding ElementName=filterButton}"
       IsOpen="{Binding ElementName=filterButton,Path=IsChecked,Mode=TwoWay}">
    <Border BorderThickness="2" BorderBrush="{StaticResource MediumBlueBrush}" Background="{StaticResource BackgroundLightBrush}" CornerRadius="5">
        <ItemsControl ItemsSource="{Binding HeaderList}"
                      Background="{StaticResource BackgroundLightBrush}"
                      Margin="1">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" Margin="5">
                        <CheckBox IsChecked="{Binding IsChecked}"/>
                        <TextBlock Text="{Binding HeaderName}"/>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Border>
</Popup>

这是该控件的外观图片

这是我的依赖属性代码

在这里你可以看到我创建了一个 RuleColumnHeader 类型的 ObservableCollection。这是我试图将我的 UserControl 设置为的项目源。

public partial class FilterDropDown : UserControl
{
    public ObservableCollection<RulesColumnHeader> ItemSource
    {
        get => (ObservableCollection<RulesColumnHeader>)GetValue(ItemSourceProperty);
        set => SetValue(ItemSourceProperty, value);
    }
    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ItemSourceProperty =
        DependencyProperty.Register("ItemSource", typeof(ObservableCollection<RulesColumnHeader>), typeof(FilterDropDown), new FrameworkPropertyMetadata(null));

    public FilterDropDown()
    {
        InitializeComponent();
    }
}

用户控制

这是我创建用户控件并将项目源绑定到我创建的依赖项属性的“尝试”。

<UserControl x:Class="YAI.BomConfigurator.Desktop.Control.FilterDropDown"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:YAI.BomConfigurator.Desktop.Control"
         xmlns:fa="http://schemas.fontawesome.io/icons/"
         mc:Ignorable="d" 
         d:DesignHeight="50" d:DesignWidth="50">
<Grid>
    <ToggleButton x:Name="filterButton" Background="Transparent" BorderThickness="0">
        <fa:ImageAwesome x:Name="border"
                         Height="15"
                         Foreground="{StaticResource MediumBlueBrush}"
                         Icon="Filter"/>
    </ToggleButton>

    <Popup x:Name="popup" 
           AllowsTransparency="True"
           StaysOpen="False"
           PlacementTarget="{Binding ElementName=filterButton}"
           IsOpen="{Binding ElementName=filterButton,Path=IsChecked,Mode=TwoWay}">

        <Border BorderThickness="2" BorderBrush="{StaticResource MediumBlueBrush}" Background="{StaticResource BackgroundLightBrush}" CornerRadius="5">
            <ItemsControl ItemsSource="{Binding ItemSource, Source={local:FilterDropDown}}"
                          Background="{StaticResource BackgroundLightBrush}"
                          Margin="1">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Margin="5">
                            <CheckBox IsChecked="{Binding IsChecked}"/>
                            <TextBlock Text="{Binding HeaderName}"/>
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Border>
    </Popup>
</Grid>

在我对 ItemsControl 的 ItemSource 绑定中,source= 部分引发错误,提示“无效的标记扩展,预期类型为 'object',实际为 FilterDropDown”。

所以这基本上就是我现在所处的位置。我不知道如何前进或从这里做什么。我试图弄清楚如何将 UserControl 项目源绑定到依赖属性。我不知道是我的语法还是我做错了整件事。如果有人可以帮助指导我,那就太好了。

谢谢,

【问题讨论】:

    标签: wpf templates binding user-controls dependency-properties


    【解决方案1】:

    ItemsSource Binding的Source属性设置错误。

    替换

    ItemsSource="{Binding ItemSource, Source={local:FilterDropDown}}"
    

    ItemsSource="{Binding ItemSource,
                          RelativeSource={RelativeSource AncestorType=UserControl}}"
    

    除此之外,将 ItemsSource 声明为 ObservableCollection 是不必要的,甚至是错误的。使用更通用的类型,例如IEnumerable

    public IEnumerable ItemSource
    {
        get => (IEnumerable)GetValue(ItemSourceProperty);
        set => SetValue(ItemSourceProperty, value);
    }
    
    public static readonly DependencyProperty ItemSourceProperty =
        DependencyProperty.Register(
            nameof(ItemSource), typeof(IEnumerable), typeof(FilterDropDown));
    

    【讨论】:

      【解决方案2】:

      在构建自定义控件时,您希望将 ItemsSource 定义为:

      public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(nameof(ItemsSource), typeof(IEnumerable),
          typeof(xxx), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnItemsSourceChanged)));
      
          public IEnumerable ItemsSource
          {
              get
              {
                  return (IEnumerable)GetValue(ItemsSourceProperty);
              }
      
              set
              {
                  SetValue(ItemsSourceProperty, value);
              }
          }
      

      OnItemsSourceChanged 不是必需的,我只是在我 c&p'ed 的代码中拥有它。

      您还希望您的控件派生自 Control。不是用户控件。因此,.cs 和 .xaml 的嵌套方式不同。它们是完全分开的。 .cs 是独立的,xaml 位于您的 Themes 文件夹中。

      public class xxx : Control
      

      并有一个静态构造函数:

      static xxx()
      {
          DefaultStyleKeyProperty.OverrideMetadata(typeof(xxx), new FrameworkPropertyMetadata(typeof(xxx)));
      }
      

      然后在您的 XAML 中,您将定义一个以 xxx 为目标的样式,并在该样式中设置 ControlTemplate。

      在那里,一般来说,您会使用 TemplateBinding 绑定来绑定属性。

      【讨论】:

        猜你喜欢
        • 2023-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-29
        • 2014-08-31
        • 2017-12-24
        • 1970-01-01
        • 2017-12-18
        相关资源
        最近更新 更多