简体   繁体   English

WPF将datagrid组合框ItemsSource更改为另一个datagrid combox的值

[英]WPF change datagrid combobox ItemsSource to value of another datagrid combox

I have a datagrid with 2 DataGridComboxClolumn elements and want to change the ItemsSource of the second when the value of the first is changed. 我有一个带有2个DataGridComboxClolumn元素的数据网格,并且想要在更改第一个的值时更改第二个的ItemsSource。 How can I set up such a binding? 如何设置这种绑定?

Note: the datagrid has it's own itemssource and the data is hierachical following: 注意:datagrid有其自己的itemssource,数据具有以下层次结构:

ItemsSource of the datagrid (list op type Channel): datagrid的ItemsSource(列表操作类型Channel):

public class Root
{
    public List<Channel> Ch { get; set; }  // This is the ItemsSource of the datagrid itself
}


public class Channel
{
    public Settings TheSettings { get; set; }
}

The thing I want to accomplish is that the TheSettings is set with selected value of the second ComboBox. 我要完成的事情是使用第二个ComboBox的选定值设置TheSettings。 This is easyly done by setting the ComboBox ItemsSource. 通过设置ComboBox ItemsSource可以轻松完成此操作。 Although I require that the ItemsSource of the second combox to be dynamic. 虽然我要求第二个combox的ItemsSource是动态的。 Eg it has to change to the source selected in the FIRST combobox. 例如,它必须更改为FIRST组合框中选择的源。 How can this be done? 如何才能做到这一点?

Option 1 选项1

You can create your a DataGridTemplateColumn with two combobox. 您可以使用两个组合框创建一个DataGridTemplateColumn The first one can be populated with items from the main ViewModel and the second one will be bound to the items of the SelectedItem of the first. 可以使用主ViewModel中的项目填充第一个,第二个将绑定到第一个的SelectedItem的项目。

<Window x:Class="WpfApplication1.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:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:local="clr-namespace:WpfApplication1"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="525"
    Height="350"
    mc:Ignorable="d">
<Window.DataContext>
    <local:Root/>
</Window.DataContext>
<Grid x:Name="LayoutRoot">
    <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Ch}" CanUserAddRows="False">
        <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <ComboBox  Width="100" ItemsSource="{Binding DataContext.ComboBox1Items, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" x:Name="ComboBox1"/>
                        <ComboBox Grid.Column="1" Width="100" ItemsSource="{Binding SelectedItem.Items, ElementName=ComboBox1}" SelectedItem="{Binding TheSettings}" IsEditable="True" IsReadOnly="True"/>
                        </Grid>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

</Grid>
</Window>

public class ComboBox1Item
{
    public string Label { get; set; }
    public List<string> Items { get; set; }

    public override string ToString()
    {
        return this.Label;
    }
}

public class Root
{
    public List<Channel> Ch { get; set; }

    public List<ComboBox1Item> ComboBox1Items { get; set; }

    public Root()
    {
        this.Ch = new List<Channel>(){
            new Channel(){ TheSettings = "Settings1"},
            new Channel(){ TheSettings = "Settings2"},
        };

        this.ComboBox1Items = new List<ComboBox1Item>{
            new ComboBox1Item(){ Label = "Item1",
                Items = new List<string>(){ "Settings1", "Settings2"}
            },
            new ComboBox1Item(){ Label = "Item2",
                Items = new List<string>(){ "Settings3", "Settings4"}
            }
        };
    }
}

Option 2 选项2

Create an object to wrap your Channel objects, and put in it the logic to allow one combobox to drive the items of the other: 创建一个对象来包装您的Channel对象,并在其中添加逻辑以允许一个组合框驱动另一个组合框的项目:

public class ChannelWrapper : INotifyPropertyChanged
{
    #region INotifyPropertyChanged values

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion


    private object comboBox1SelectedItem;
    public object ComboBox1SelectedItem
    {
        get { return this.comboBox1SelectedItem; }
        set
        {
            if (this.comboBox1SelectedItem != value)
            {
                this.comboBox1SelectedItem = value;
                this.OnPropertyChanged("ComboBox1SelectedItem");

                // Put the logic to change the items available in the second combobox here
                if (value == "Value1")
                    this.ComboBox2ItemsSource = new List<object>() { "Setting1", "Setting2" };
                if (value == "Value2")
                    this.ComboBox2ItemsSource = new List<object>() { "Setting3", "Setting4" };
            }
        }
    }

    private List<object> comboBox2ItemsSource;
    public List<object> ComboBox2ItemsSource
    {
        get { return this.comboBox2ItemsSource; }
        set
        {
            if (this.comboBox2ItemsSource != value)
            {
                this.comboBox2ItemsSource = value;
                this.OnPropertyChanged("ComboBox2ItemsSource");
            }
        }
    }

    public Channel Ch { get; set; }
}

Your Root class would then expose a collection of wrappers instead a collection of channels. 然后,您的Root类将公开包装器集合,而不是通道集合。 Your DataGrid would have 2 ComboBoxColumns. 您的DataGrid将具有2个ComboBoxColumns。 The SelectedItem of the first would be bound to the property "ComboBox1SelectedItem" of the wrapper. 第一个的SelectedItem将绑定到包装的属性“ ComboBox1SelectedItem”。 The ItemsSource of the second would be bound to the property "ComboBox2ItemsSource" of the wrapper and the SelectedItem of the second column would be bound the setting of the Channel instance of the wrapper, with the path "Ch.TheSettting". 第二个的ItemsSource将绑定到包装器的属性“ ComboBox2ItemsSource”,第二列的SelectedItem将绑定到包装器的Channel实例的设置,路径为“ Ch.TheSettting”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM