代码之家  ›  专栏  ›  技术社区  ›  Erik Thysell

c#wpf组合框将源绑定到一个集合,并将项作为另一个集合的属性

  •  0
  • Erik Thysell  · 技术社区  · 6 年前

    我想把 itemssource combobox 对象的属性( Source1 )集合到另一个对象的属性( MyCollection )在a中 DataGridTemplateColumn 在a中 DataGrid :

    查看:

    <Window x:Class="TestWPF.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:TestWPF"
            mc:Ignorable="d"
            Title="Test WPF" Height="350" Width="525">
        <Window.DataContext>
            <local:ViewModel></local:ViewModel>
        </Window.DataContext>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Label Content="Testing DATAGRIDTEMPLATECOLUMN with COMBOBOX" FontFamily="Verdana" FontSize="16" Grid.Column="0" Grid.Row="0"/>
            <DataGrid Grid.Column="0" Grid.Row="1" ItemsSource="{Binding MyCollection}" CanUserAddRows="True" AutoGenerateColumns="False">
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding Name}" Header="Name of person"/>
                    <DataGridTemplateColumn Header="Age of person" >
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Grid>
                                    <ComboBox ItemsSource="{Binding Path=DataContext.Source1,
                                            RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}"
                                                  SelectedValue="{Binding Age}" DisplayMemberPath="Number"/>
                                </Grid>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTextColumn Binding="{Binding Salary}" Header="Persons salary"/>
                </DataGrid.Columns>
            </DataGrid>
            <!-- Just for checking -->
            <DataGrid Grid.Column="0" Grid.Row="2" ItemsSource="{Binding MyCollection}" CanUserAddRows="True" AutoGenerateColumns="True"/>
        </Grid>
    </Window>
    

    ViewModel(模型(包括视图类的其余部分)):

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Windows;
    
    namespace TestWPF
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            ViewModel vm;
            public MainWindow()
            {
                InitializeComponent();
    
            }
    
    
        }
    
        public class ViewModel : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            }
    
            private ObservableCollection<MyClass> _myCollection;
    
            private ObservableCollection<Source1> _source1;
    
            public ObservableCollection<Source1> Source1
            {
                get { return _source1; }
                set { _source1 = value; }
            }
    
    
            public ViewModel()
            {
                _source1 = new ObservableCollection<TestWPF.Source1>();
                _myCollection = new ObservableCollection<MyClass>();
                SetupSource();
    
            }
    
            private void SetupSource()
            {
                _source1.Add(new TestWPF.Source1(2));
                _source1.Add(new TestWPF.Source1(3));
                _source1.Add(new TestWPF.Source1(5));
                _source1.Add(new TestWPF.Source1(8));
            }
    
            public ObservableCollection<MyClass> MyCollection
            {
                get { return _myCollection; }
                set { _myCollection = value; NotifyPropertyChanged(nameof(MyCollection)); }
            }
    
    
        }
    }
    

    最后是Source1类:

    namespace TestWPF
    {
        public class Source1
        {
            public int Number { get; set; }
    
            public Source1(int n)
            {
                Number = n;
            }
        }
    }
    

    和MyClass:

    namespace TestWPF
    {
        public class MyClass
        {
            public string Name { get; set; }
            public int Age { get; set; }
            public double Salary { get; set; }
    
            public MyClass()
            {
    
            }
            public MyClass(string n, int a, double s)
            {
                Name = n;
                Age = a;
                Salary = s;
            }
        }
    }
    

    当我运行此命令时,会收到错误和建议,以创建Source1到的转换器 System.Int32 。我以为 SelectedValue="{Binding Age}" ComboBox 将连接 MyClass DisplayedMemberPath 。 有没有办法用这种方式连接两个不同类的两个属性,或者有必要创建一个转换器? 我想创造一个 read-only 属性,该属性将返回 Source1.Number 使用Linq从Source1集合中删除,并将其用作 Itemssource 对于 下拉列表框 但我想知道与使用转换器相比,这是否是一种糟糕的做法?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Andy    6 年前

    我认为您的问题是因为您没有在组合上设置所有需要的属性。

    尝试

    <ComboBox ItemsSource="{Binding Path=DataContext.Source1,
              RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}}"
              SelectedValue="{Binding Age}"
              SelectedValuePath="Number" 
              DisplayMemberPath="Number"/>
    

    Source1可能只有一个属性,但combobox并不智能,因此它试图将int设置为Source1的实例,而不是int。