1

ComboBoxを含むDataGridCellがあります。

その「SelectionChanged」イベントを発生させたときに、別の列(最終的には実行時のセル)のCollectionViewSourceに、この行で選択した値に従ってデータを入力する必要があります。

多分DataTrigger、ActionTrigger、EventTrigger、多分コード、XAML私は気にしない、私はただ解決策が必要です。

どうもありがとう!

関連:DataGridCells、動的カスケードComboBox間の制御へのアクセス

4

1 に答える 1

4

私があなたの質問を正しく理解している場合は、DataGridの同じ行にある別のセルのコンボボックスの選択に基づいて、セルのコンボボックスの内容を入力します。そうであれば:

最初の解決策(IMOが望ましい)

行データ(データオブジェクトの単純なラッパー)を表すViewModelを作成します。宛先ComboBoxのItemsSource-propertyを、IEnumerableビューモデルから提供する-propertyにバインドします。SelectedItemをsource-ComboBoxからViewModelの別のプロパティにバインドします。このソースプロパティがViewModelで変更されるたびに、ViewModelによって提供されるリストの内容を変更します。

宛先(リスト)プロパティに使用しますObservableCollection<T>。ソースプロパティはあなた次第です。

これはおおよその例です。私はクラスVM(ViewModel用)と呼んでいますが、これは現在のソリューションでは何も変わりません。MVVMは部分的に使用することもできます。

public class DataObjectVM : DependencyObject {

    public static readonly DependencyProperty SelectedCategoryProperty =
        DependencyProperty.Register("SelectedCategory", typeof(CategoryClass), typeof(DataObjectVM), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,delegate (DependencyObject d,DependencyPropertyChangedEventArgs e){
            ((DataObjectVM)d).SelectedCategoryChanged(e);
        }));

    ObservableCollection<ItemClass> _items=new ObservableCollection<ItemClass>();


    void SelectedCategoryChanged(DependencyPropertyChangedEventArgs e) {

        // Change here the contents of the _items collection. 
        // The destination ComboBox will update as you desire
        // Do not change the _items reference. Only clear, add, remove or
        //  rearange the collection-items

    }

    // Bind the destination ComboxBox.ItemsSource to this property
    public IEnumerable<ItemClass> DestinationItems {
        get {
            return _items;
        }
    }
    // Bind to this property with the source ComboBox.SelectedItem
    public CategoryClass SelectedCategory {
        get { return (CategoryClass)GetValue(SelectedCategoryProperty); }
        set { SetValue(SelectedCategoryProperty, value); }
    }

}

このクラスにコンストラクターを追加して、データオブジェクトを取得し、いくつかのラッパープロパティを作成して、残りのプロパティをDataGridで提供する必要があります。それらがたくさんある場合は、データオブジェクトとそれに直接バインドするプロパティを1つ作成することもできます。良くありませんが、それは仕事をします。また、ビジネスオブジェクトのデータを使用してSelectedCategoryを事前に初期化することもできます(必須)。コンストラクターでもこれを行います。DataGridのItemsSourceとして、表示するすべてのアイテムをラップするDataObjectVMクラスのIEnumerableを指定します。


VisualTreeHelperを使用した別の方法

手動で実行する場合は、ComboBox.SelectionChangedEventのハンドラーの背後にあるコードに登録し、宛先のComboBox手動のItemsSourceを変更します。EventArgsで取得するビジネスオブジェクト。ビジュアルツリーで検索する必要のある宛先ComboBox(VisualTreeHelperを使用)。クラスを使用し、対応するComboBoxでDataGridTemplateColumnを追加する場合も、イベントを配線できます。DataTemplate

しかし、これは実際にはそれほど簡単ではなく、エラーが発生しやすいと思います。上記の解決策ははるかに簡単です。

これがあなたがおそらく探しているコードです:

private void CboSource_SelectionChanged(object sender, SelectionChangedEventArgs e) {
    ComboBox cbo = (ComboBox)sender;
    FrameworkElement currentFe = VisualTreeHelper.GetParent(cbo) as FrameworkElement;
    while (null != currentFe && !(currentFe is DataGridRow)) {
        currentFe = VisualTreeHelper.GetParent(currentFe) as FrameworkElement;
    }
    if (null != currentFe) {
        List<ComboBox> list = new List<ComboBox>();
        FindChildFrameworkElementsOfType<ComboBox>(currentFe,list);
        // Requirement 1: Find ComboBox
        foreach (ComboBox cboFound in list) {
            if (cboFound.Name == "PART_CboDestination") {
                // This is the desired ComboBox
                // Your BO is available through cbo.Found.DataContext property
                // If don't like to check the name, you can also depend on the
                // sequence of the cbo's because I search them in a deep search
                // operation. The sequence will be fix.
            }
        }

        List<DataGridCell> cells = new List<DataGridCell>();
        FindChildFrameworkElementsOfType<DataGridCell>(currentFe,cells);
        // Requirement 2: Find Sibling Cell
        foreach (DataGridCell cell in cells) {
            // Here you have the desired cell of the other post
            // Take the sibling you are interested in
            // The sequence is as you expect it

            DataGridTemplateColumn col=cell.Column as DataGridTemplateColumn;
            DataTemplate template = col.CellTemplate;

            // Through template.Resources you can access the CollectionViewSources
            // if they are placed in the CellTemplate.
            // Change this code if you will have an edit cell template or another
            // another construction

        }
    }            
}

void FindChildFrameworkElementsOfType<T>(DependencyObject parent,IList<T> list) where T: FrameworkElement{            
    DependencyObject child;
    for(int i=0;i< VisualTreeHelper.GetChildrenCount(parent);i++){            
        child = VisualTreeHelper.GetChild(parent, i);
        if (child is T) {
            list.Add((T)child);
        }
        FindChildFrameworkElementsOfType<T>(child,list);
    }
}

そして、これは私が使用したマークアップです:

<DataGrid.Columns>                        
    <DataGridTemplateColumn Header="Source" >
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox Name="PART_CboSource" SelectionChanged="CboSource_SelectionChanged" ItemsSource="!!YOUR ITEMS SOURCE!!" SelectedItem="{Binding Category}">                            
                </ComboBox>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
    <DataGridTemplateColumn Header="Destination">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ComboBox Name="PART_CboDestination"/>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
</DataGrid.Columns>

CollectionViewSourceへのアクセス

CollectionViewSourceにアクセスするには、パネルではなく、対応するDataTemplateのリソースセクションに配置します。そうすれば、それらに直接アクセスできます。IMOは、グリッドのリソースコンテナよりも適切なこの場所です。

これを行いたくない場合は、次の投稿の状態を確認してください。

DataTemplateの論理ツリーを取得する方法

于 2010-07-10T22:32:05.530 に答える