5

ユーザーがクリックしたときに WPF DataGrid の詳細行を折りたたみ、もう一度クリックしたときに再表示する必要がありました。また、単一選択を使用して、VisibleWhenSelected の DataGridRoDetailsVisibilityMode を保持したいと考えました。

他の場所でのこの投稿に基づいて、このソリューションを思いつきました: 41df-9ab9-8d93993e114c

    private bool _rowSelectionChanged;


    private void dgCompletedJobs_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        _rowSelectionChanged = true;
    }

    private void dgCompletedJobsMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
    {
        DependencyObject dep = (DependencyObject)e.OriginalSource;

        //navigate up the tree
        while (dep != null &&
            !(dep is DataGridCell) &&
            !(dep is DataGridColumnHeader))
        {
            dep = VisualTreeHelper.GetParent(dep);
        }

        if (dep == null)
        {
            return;
        }

        DataGridCell dgc = dep as DataGridCell;
        if (dgc != null)
        {
            //navigate further up the tree
            while (dep != null && !(dep is DataGridRow))
            {
                dep = VisualTreeHelper.GetParent(dep);
            }

            DataGridRow dgr = dep as DataGridRow;
            DataGrid dg = sender as DataGrid;
            if (dg != null && dgr != null)
            {
                if (dgr.IsSelected && !_rowSelectionChanged)
                {
                    dg.RowDetailsVisibilityMode =
                        (dg.RowDetailsVisibilityMode == DataGridRowDetailsVisibilityMode.VisibleWhenSelected)
                            ? DataGridRowDetailsVisibilityMode.Collapsed
                            : DataGridRowDetailsVisibilityMode.VisibleWhenSelected;
                }
                else
                {
                    dg.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.VisibleWhenSelected;
                }
            }
        }
        _rowSelectionChanged = false;
    }

これは私の問題をうまく解決しているように見えますが、特にこのプロジェクトで MVVM を使用しているため、これをより簡単かつエレガントに行うことができるのではないかと思います。ただし、これは純粋にプレゼンテーション ロジックであるため、イベント ドリブンのコード ビハインドの許容可能な使用法と考えています。

誰もがよりクリーンなソリューションを持っていますか?

4

4 に答える 4

5

「適切な」MVVM でこれを行うには、RowDetailsVisibilityMode をビュー モデルのプロパティにバインドする必要があります。

<DataGrid x:Name="dgCompletedJobs" RowDetailsVisibilityMode="{Binding RowDetailsVisible}"/>

ビュー モデル プロパティは次のようになります。

private DataGridRowDetailsVisibilityMode _rowDetailsVisible;
public DataGridRowDetailsVisibilityMode RowDetailsVisible
{
    get { return _rowDetailsVisible; }
    set {
        _rowDetailsVisible = value;
        if (PropertyChanged != null) {
             PropertyChanged(this, new PropertyChangedEventArgs("RowDetailsVisible"));
        }
    }
}

マウス クリック イベントをプロパティの変更に関連付けるには、ここに示されているように、凝った付加動作コマンドを実行するか、コード ビハインドを使用してビュー モデルを直接呼び出すことができます (私は単純なタスクのためにこれを自分で行うことがよくあります)。

private void dgCompletedJobsMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
    Window1ViewModel viewModel = (Window1ViewModel)DataContext;
    if (viewModel.RowDetailsVisible == DataGridRowDetailsVisibilityMode.Collapsed) {
        viewModel.RowDetailsVisible = DataGridRowDetailsVisibilityMode.VisibleWhenSelected;
    } else {
        viewModel.RowDetailsVisible = DataGridRowDetailsVisibilityMode.Collapsed;
    }
}
于 2012-11-13T09:29:49.363 に答える
1

送信者パラメーターを使用しないのはなぜですか? イベントが DataGrid で定義されている場合、送信者は常に DataGrid です。nullが安全であることをチェックする安全なキャストを使用しますが、それでうまくいくはずです。

ビジュアル ツリーを介して元のソースから DataGrid に戻るため、コードは不必要に複雑に見えます。

        private void dataGridMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        DataGrid dg = sender as DataGrid;
        if (dg == null)
            return;
        if (dg.RowDetailsVisibilityMode == DataGridRowDetailsVisibilityMode.VisibleWhenSelected)
            dg.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.Collapsed;
        else
            dg.RowDetailsVisibilityMode = DataGridRowDetailsVisibilityMode.VisibleWhenSelected;
    }
于 2012-11-13T08:35:56.200 に答える