无法将UserControl绑定到ItemsControl

时间:2019-04-11 20:11:31

标签: c# wpf data-binding user-controls itemscontrol

我试图用一些UserControl填充ItemsControl,但是我无法找到哪个祖先应该与数据模板中的项目匹配。

我已经尝试使用x:Name属性进行绑定,并且结果相同。 我也尝试了在没有绑定RelativeSource的情况下进行绑定,并且在绑定方面也没有任何成功。

用户控制XAML

<UserControl x:Class="FireAntTempConfigurer.UserControls.CommandButton_UC"
             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:FireAntTempConfigurer.UserControls"
             xmlns:materialDesign="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
             mc:Ignorable="d" 
             TextElement.Foreground="{DynamicResource MaterialDesignPaper}"
             d:DesignHeight="50 " d:DesignWidth="50"
             >
    <Grid>
        <Button Height="50" Padding="0,0,0,0" ToolTip="{Binding Path=Placeholder, RelativeSource={RelativeSource AncestorType=UserControl}}">
            <Button.Content>
                <materialDesign:PackIcon Kind="{Binding Path=Icon, RelativeSource={RelativeSource AncestorType=UserControl}}" Height="50" Width="50" />
            </Button.Content>
        </Button>
    </Grid>
</UserControl>

后面的用户控制代码

    /// <summary>
    /// Interaction logic for CommandButton_UC.xaml
    /// </summary>
    public partial class CommandButton_UC : UserControl
    {

        public CommandButton_UC()
        {
            this.DataContext = this;
            InitializeComponent();
        }

        public string Icon
        {
            get { return (string)GetValue(IconProperty); }
            set { SetValue(IconProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Icon.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IconProperty =
            DependencyProperty.Register("Icon", typeof(string), typeof(CommandButton_UC), new PropertyMetadata("EmoticonDead"));

        public string Placeholder
        {
            get { return (string)GetValue(PlaceholderProperty); }
            set { SetValue(PlaceholderProperty, value); }
        }
        // Using a DependencyProperty as the backing store for Placeholder.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PlaceholderProperty =
            DependencyProperty.Register("Placeholder", typeof(string), typeof(CommandButton_UC), new PropertyMetadata("fail to load"));

    }

主窗口XAML

<Window x:Class="FireAntTempConfigurer.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:FireAntTempConfigurer"
        xmlns:materialDesign="clr-namespace:MaterialDesignThemes.Wpf;assembly=MaterialDesignThemes.Wpf"
        xmlns:uc="clr-namespace:FireAntTempConfigurer.UserControls"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        TextElement.Foreground="{DynamicResource SecondaryAccentBrush}"
        Background="{DynamicResource MaterialDesignPaper}"
        TextElement.FontWeight="Medium"
        TextElement.FontSize="20"
        FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
        x:Name="mw">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="95*"/>
            <ColumnDefinition Width="169*"/>
            <ColumnDefinition Width="95*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="150"/>
            <RowDefinition Height="50"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        <materialDesign:Card Grid.Column="1" Grid.Row="1">
            <StackPanel Margin="0">
                <TextBlock>ToolBox:</TextBlock>
                <Separator Margin="0"></Separator>
                <ItemsControl ItemsSource="{Binding Path=MyPropertyList, RelativeSource={RelativeSource AncestorType=Window}}">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel  Orientation="Horizontal" Height="50" HorizontalAlignment="Left" Margin="5,0,0,0" IsItemsHost="True"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate >
                        <DataTemplate>
                            <uc:CommandButton_UC Padding="0,0,0,0" Margin="0,0,5,0" 
                                                 Icon="{Binding Path=IconProp, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
                                                 Placeholder="{Binding Path=PlaceHolderProp , RelativeSource={RelativeSource AncestorType=ItemsControl}}">
                            </uc:CommandButton_UC>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
.
.
.

后面的主窗口代码

public partial class MainWindow : Window
{
    public CommandButtonViewModel MyProperty { get; set; }
    public BindingList<CommandButtonViewModel> MyPropertyList { get; set; }
    public MainWindow()
    {
        MyPropertyList = new BindingList<CommandButtonViewModel>();
        MyProperty = new CommandButtonViewModel { IconProp = "PlusCircleOutline", PlaceHolderProp = "Add" };
        BindingList<CommandButtonViewModel> tempList = new BindingList<CommandButtonViewModel>();
        tempList.Add(MyProperty);
        tempList.Add(MyProperty);
        MyPropertyList = tempList;
        DataContext = this;
        InitializeComponent();
    }

现在我在输出中收到消息:

System.Windows.Data Error: 40 : BindingExpression path error: 'IconProp' property not found on 'object' ''CommandButton_UC' (Name='')'. BindingExpression:Path=IconProp; DataItem='CommandButton_UC' (Name=''); target element is 'CommandButton_UC' (Name=''); target property is 'Icon' (type 'String')
System.Windows.Data Error: 40 : BindingExpression path error: 'IconProp' property not found on 'object' ''CommandButton_UC' (Name='')'. BindingExpression:Path=IconProp; DataItem='CommandButton_UC' (Name=''); target element is 'CommandButton_UC' (Name=''); target property is 'Icon' (type 'String')
System.Windows.Data Error: 40 : BindingExpression path error: 'PlaceHolderProp' property not found on 'object' ''ItemsControl' (Name='')'. BindingExpression:Path=PlaceHolderProp; DataItem='ItemsControl' (Name=''); target element is 'CommandButton_UC' (Name=''); target property is 'Placeholder' (type 'String')
System.Windows.Data Error: 40 : BindingExpression path error: 'PlaceHolderProp' property not found on 'object' ''ItemsControl' (Name='')'. BindingExpression:Path=PlaceHolderProp; DataItem='ItemsControl' (Name=''); target element is 'CommandButton_UC' (Name=''); target property is 'Placeholder' (type 'String')

不胜感激

1 个答案:

答案 0 :(得分:1)

我无法完全复制您的代码,因为我没有materialdesignlibrary,但是我想我可以重现您的情况,用普通的wpf控件替换那些引用。 我认为您必须执行以下步骤:

  1. 检查CommandButtonViewModel确实是一个视图模型,因此必须实现INotifyPropertyChanged,如下所示:

    public class CommandButtonViewModel : INotifyPropertyChanged  
    {   
        private string _iconprop;
        public string IconProp
        {
            get
            {
                return _iconprop;
            }
            set
            {
                _iconprop = value;
                NotifyPropertyChanged("IconProp");
            }
        }
    
    private string _placeholderprop;
    public string PlaceHolderProp
    {
        get
        {
            return _placeholderprop;
        }
        set
        {
            _placeholderprop = value;
            NotifyPropertyChanged("PlaceHolderProp");
        }
    }
    
    public event PropertyChangedEventHandler PropertyChanged;
    
    private void NotifyPropertyChanged(String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    }

    1. 您的DataContext只是主窗口,因此请从CommandButton_UC的创建者中删除DataContext的集合

      public partial class CommandButton_UC : UserControl
      {
          public CommandButton_UC()
          {
              InitializeComponent();
          }
      }
      
    2. 在绑定中,您可以直接绑定到CommandButtonViewModel属性

    所以您必须以这种方式修改CommandButton_UC:

    <ItemsControl 
      ItemsSource="{Binding Path=MyPropertyList, 
                    RelativeSource {RelativeSource AncestorType=Window}}">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel  
                                 Orientation="Horizontal" 
                                 Height="50" 
                                 HorizontalAlignment="Left" 
                                 Margin="5,0,0,0" IsItemsHost="True"/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate >
                            <DataTemplate>
                                <uc:CommandButton_UC 
                                    Padding="0,0,0,0" Margin="0,0,5,0" 
                                    Icon="{Binding Path=IconProp}"
                                    Placeholder="{Binding Path=PlaceHolderProp}">
                                </uc:CommandButton_UC>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>