質問

I've a problem with the WPF datagrid. I have two ComboBox columns and the second one should set it's datacontext dependant of what is selected in the first one.

ViewModel

public class MyCollection: AbstractViewModel
{
    private BindingList<string> _subitems;
    public BindingList<string> Subitems
    {
        get { return _subitems; }
        set { _subitems = value; Notify("Subitems");}
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; Notify("Name");}
    }
}

Xaml

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding SelectedName}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ComboBox SelectedValuePath="Name"
                      x:Name="CollectionBox"
                      SelectedValue="{Binding SelectedName}"
                      DisplayMemberPath="Name"
                      ItemsSource="{Binding SomeBinding}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn >
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding SelectedSubitem}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
    <DataGridTemplateColumn.CellEditingTemplate>
        <DataTemplate>
            <ComboBox SelectedValue="{Binding SelectedSubitem}"
                      ItemsSource="{Binding ElementName=CollectionBox, Path=SelectedItem.Subitems}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

The binding for my first ComboBox is ok but I did not see any items in my second ComboBox (the viewmodel has entries for booth of the ComboBoxes); only the TextBox binding works as expected. I tryed it with a ComboBoxColumn as well but with the same result.

役に立ちましたか?

解決

here an simple working example how you could use your ViewModel to achieve your needs

XAML

   <DataGrid ItemsSource="{Binding Source}" Width="500">
        <DataGrid.Columns>
        <DataGridTemplateColumn Header="main" Width="100">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding SelectedName}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox SelectedValuePath="Name"                      
                                  SelectedValue="{Binding SelectedName}"                                  
                                  SelectedItem="{Binding SelectedMainItem, UpdateSourceTrigger=PropertyChanged}"                      
                                  DisplayMemberPath="Name"                      
                                  ItemsSource="{Binding SomeBinding}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="sub" Width="100">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding SelectedSubitem}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <ComboBox SelectedValue="{Binding SelectedSubitem}"                      
                                  ItemsSource="{Binding  Path=SelectedMainItem.Subitems}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

code behind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new VMColl();
    }
}

public class VMColl
{
    List<VM> source;

    public List<VM> Source
    {
        get { return source; }
        set { source = value; }
    }

    public VMColl()
    {
        source  = new List<VM>(){new VM(),new VM(),new VM(),new VM()};
    }
}

/// <summary>
/// your Row
/// </summary>
public class VM : Notify
{
    private List<mainObj> _items;
    public List<mainObj> SomeBinding
    {
        get { return _items; }
        set
        {
            _items = value;
            OnPropertyChanged("Items");
        }
    }

    private string _selectedName;
    public string SelectedName
    {
        get { return _selectedName; }
        set
        {
            _selectedName = value;
            OnPropertyChanged("SelectedName");
        }
    }

    private mainObj _selectedMainItem;
    public mainObj SelectedMainItem
    {
        get { return _selectedMainItem; }
        set
        {
            _selectedMainItem = value;
            OnPropertyChanged("SelectedMainItem");
            OnPropertyChanged("SelectedMainItem.Subitems");
        }
    }

    private string _selectedSubitem;
    public string SelectedSubitem
    {
        get { return _selectedSubitem; }
        set
        {
            _selectedSubitem = value;
            OnPropertyChanged("SelectedSubitem");
        }
    }

    public VM()
    {
        SomeBinding = new List<mainObj>() {new mainObj("first"),new mainObj("second"),new mainObj("someother") };
    }
}

public class mainObj : Notify
{
    private BindingList<string> _subitems;
    public BindingList<string> Subitems
    {
        get { return _subitems; }
        set
        {
            _subitems = value;
            OnPropertyChanged("Subitems");
        }
    }

    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged("Name");
        }
    }

    public mainObj(string name)
    {
        _name = name;
        _subitems = new BindingList<string>(){"1","2","3"};
    }
}

public class Notify : INotifyPropertyChanged
{
    // Declare the event 
    public event PropertyChangedEventHandler PropertyChanged;

    // Create the OnPropertyChanged method to raise the event 
    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

他のヒント

An update of @WiiMaxx answer :

To get selected subitem's value, you have to add a trigger in the second combobox :

 <DataTemplate>
         <ComboBox SelectedValue="{Binding SelectedSubitem , UpdateSourceTrigger=PropertyChanged}"                      
                       ItemsSource="{Binding  Path=SelectedMainItem.Subitems}" />
 </DataTemplate>
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top