【问题标题】:WPF Bindings of a Custom User Control with a ComboBox containing a DataTemplate自定义用户控件与包含 DataTemplate 的 ComboBox 的 WPF 绑定
【发布时间】:2022-01-12 20:07:54
【问题描述】:

我正在尝试创建一个自定义用户控件,其中包含一个 ListView,其中包含如下所示的数据模板:

        <ComboBox  ItemsSource="{Binding ItemsSource, ElementName=root}" 
               SelectedItem="{Binding SelectedItem, ElementName=root, Mode=TwoWay}">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">                        
                    
                    <!-- This is what I tried:
                    
Working but not what I want                 <TextBox Text="{Binding Name}"/>    
Returns the List only the word "FallBack"   <TextBox Text="{Binding ItemText, ElementName=root}" />
Returns the LIst empty                      <TextBox Text="{Binding ItemText}" />
                    -->
                    
                </StackPanel>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>

在后面的代码中,我为这种情况创建了必要的依赖属性(所以我假设)唯一相关的是关于项目文本,它看起来像这样:

    #region ItemText

    public string ItemText
    {
        get { return (string)GetValue(ItemTextProperty); }
        set { SetValue(ItemTextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ItemText.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ItemTextProperty =
        DependencyProperty.Register("ItemText", typeof(string), typeof(CardComboBox), new PropertyMetadata("FallBack"));

    #endregion

我想做的是像这样添加用户控件

  <local:CardComboBox ItemsSource="{Binding Persons}" SelectedItem="{Binding SelectedPerson}" ItemText="{Binding Name}" IsEnabled="True" />

选项一:

<TextBox Text="{Binding Name}"/>

工作正常,因为类 Person 的 PropertyName 是 Name,但我显然不想硬编码它。我想将它绑定到我喜欢的任何属性。

选项 2:

<TextBox Text="{Binding ItemText, ElementName=root}" />

给我 7 个项目的列表(根据列表),但由于 DependencyPropertyMetadata 仅显示单词“Fallback”。

选项 3:

<TextBox Text="{Binding ItemText}" />

给我列表,但根本没有文字。

我也尝试使用 relativeSource,但结果相似。

   #region Person

    Person _selectedPerson;
    public Person SelectedPerson
    {
        get => _selectedPerson;
        set
        {
            if (value != _selectedPerson)
            {
                _selectedPerson = value;
                OnPropertyChanged("SelectedPerson");

            }
        }
    }


    ObservableCollection<Person> _persons;
    public ObservableCollection<Person> Persons
    {
        get => _persons;
        set
        {
            if (value != _persons)
            {
                _persons = value;
                OnPropertyChanged("Persons");

            }
        }
    }

    public void populatePersons()
    {
        Persons = new ObservableCollection<Person>();  
        Persons.Add(new Person("Carl"));
        Persons.Add(new Person("Max"));
        Persons.Add(new Person("May"));
        Persons.Add(new Person("Jen"));
        Persons.Add(new Person("Charly"));
        Persons.Add(new Person("Nora"));
        Persons.Add(new Person("Yvonne"));
    }

    #endregion

我已经添加了我要绑定的列表。方法 Populate Persons 在 ViewModel 的构造函数中被调用。

【问题讨论】:

    标签: wpf listview combobox binding user-controls


    【解决方案1】:

    &lt;TextBox Text="{Binding ItemText, RelativeSource={RelativeSource AncestorType=local:CardComboBox}}" /&gt;TextBox 绑定到父CardComboBoxItemText 依赖属性的当前值,如果这是你想要的。

    但是,如果要显示每个 Person 字节的 Name 属性的值,您还希望能够使用 ItemText 属性指定要绑定到的 Person 属性的名称,您必须以编程方式创建绑定。

    【讨论】:

    • 谢谢,不幸的是,这给了我与选项 2 类似的结果,即单词“FallBack”的列表
    • 一份清单?请解释一下你的意思。我猜你当时没有设置ItemText 的值?如果将其设置为 &lt;local:CardComboBox ... ItemText="Test" /&gt; 之类的常量值会怎样?
    • List 我的意思是当你打开 ComboBox 时的列表......这 7 个项目对应于绑定到 ItemsSource 的 ObservableCollection Persons 中的 7 个对象。当我按照你的建议做时,我会得到 7 次测试
    • 您阅读我的问题了吗?您绑定到的属性的值是多少?你在哪里以及如何设置它?
    • @CKnodyvara 您不必担心DataTemplateDataTemplate 不是通用控件的作者关心的问题。只需提供布局和数据主机。让控件的用户为他的数据定义DataTemplate。这就是它的完成方式。否则,您将没有机会创建通用控件(这听起来像是您的目标)。您可以考虑将ItemTemplate 依赖属性添加到您的UserControl 并将其绑定到ComboBox
    【解决方案2】:

    目前最接近的解决方案是公开 ItemContentTemplate 依赖属性,然后将其绑定到静态资源(例如来自 App.xaml)

    UserControl 的 XAML 如下所示:

         <StackPanel Style="{StaticResource CardStackPanel}" Orientation="{Binding Orientation, ElementName=root}" >
            <Label  x:Name="Label" Content="{Binding TitleText, ElementName=root}"/>
            <ComboBox ItemsSource ="{Binding ItemsSource,           RelativeSource={RelativeSource AncestorType=UserControl}}" 
                      ItemTemplate="{Binding ItemContentTemplate,   RelativeSource={RelativeSource AncestorType=UserControl}}" 
                      SelectedItem="{Binding SelectedItem,          RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay}" />
     </StackPanel>
    

    组合框部分的代码:

            public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CardComboBox));
        public IEnumerable ItemsSource
        {
            get { return (IEnumerable)GetValue(ItemsSourceProperty); }
            set { SetValue(ItemsSourceProperty, value); }
        }
    
    
        public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(CardComboBox));
        public object SelectedItem
        {
            get { return GetValue(SelectedItemProperty); }
            set { SetValue(SelectedItemProperty, value); }
        }
    
        public DataTemplate ItemContentTemplate
        {
            get { return (DataTemplate)GetValue(ItemContentTemplateProperty); }
            set { SetValue(ItemContentTemplateProperty, value); }
        }
        public static readonly DependencyProperty ItemContentTemplateProperty =
            DependencyProperty.Register("ItemContentTemplate", typeof(DataTemplate), typeof(CardComboBox));
    

    App.xaml 中的静态资源(示例):

        <DataTemplate x:Key="FirstNamesTemplate">
            <Label Content="{Binding FirstName}"/>
        </DataTemplate>
    

    ComboBoxCard 的实现现在看起来像这样:

    <local:CardComboBox ItemsSource="{Binding PersonModels}" SelectedItem="{Binding SelectedPersonModel, Mode=TwoWay}" ItemContentTemplate="{StaticResource FirstNamesTemplate}" TitleText="With StaticResource" IsEnabled="False"/>
    

    此模式允许在自定义用户控件中实现组合框或列表视图。

    【讨论】:

    • 为什么要定义ItemsSourceItemContentTemplate 属性而不是从ItemsSource 继承?
    猜你喜欢
    • 2016-03-11
    • 2021-08-10
    • 2011-07-05
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    • 2016-05-11
    • 1970-01-01
    相关资源
    最近更新 更多