3

関連する 3 つの異なる DataGrids を xaml からコードにリファクタリングし、コンテキスト メニューのヘッダー テキストを更新する際に問題が発生しました。

コマンドとテキストは、どのデータ グリッド セルが現在のセルであるかに従って更新する必要があります。ヘッダー テキストは xaml で正常に更新されましたが、下の図からわかるように、空の文字列として表示されるようになりました。コマンド自体は正しく機能し、正しいグリッド セルで機能します。

ヘッダー テキストの setter fires プロパティが変更されましたが、コードが xaml の同等の方法でバインディングを複製していないと思われます。また、共有属性がコードで説明する必要があるものかどうかもわかりません。

私が使用しているコードを改善する方法を知っている人はいますか?

乾杯、
ベリル

ここに画像の説明を入力

バインディングを確立するための XAML スタイル

<ContextMenu x:Key="NonProjectActivityContextMenu" x:Shared="true">

    <MenuItem 
        DataContext="{Binding MakeEachWeekDayFullDayCommand}" Command="{Binding .}" 
        Header="{Binding HeaderText}" InputGestureText="{Binding InputGestureText}"      
        />
    <MenuItem 
        DataContext="{Binding MakeFullDayCommand}" Command="{Binding .}" 
        Header="{Binding HeaderText}" InputGestureText="{Binding InputGestureText}"      
        />
</ContextMenu>

<!-- Bindings assumes a VmMenuItem (Command Reference) -->
<Style x:Key="ContextMenuItemStyle" TargetType="{x:Type MenuItem}">
    <Setter Property="Header" Value="{Binding HeaderText}"/>
    <Setter Property="InputGestureText" Value="{Binding InputGestureText}" />
    <Setter Property="Command" Value="{Binding Command}" />
    <Setter Property="Icon" Value="{Binding Icon}" />
    <Setter Property="Tag" Value="{Binding IdTag}" />
    <Setter Property="ItemsSource" Value="{Binding Children}"/>
</Style>

コード

    protected virtual ContextMenu _GetContextMenu() {
        var menuItems = _dataContext.MenuItems.Select(menuItem => menuItem.ToMenuItem());
        var cm = new ContextMenu();
        foreach (var item in menuItems) {
            cm.Items.Add(item);
        }
        return cm;
    }

アップデート

空の文字列部分は私の愚かさでした。ヘッダー テキストを初期化していませんでした。下の写真は私が今得たもので、改善されています。テキストが更新されて、曜日が表示されます。つまり、"Make Monday a full day" です。 ここに画像の説明を入力

エルノの編集

以下のようにグリッド自体の列とスタイルを設定しているので、コンテキストメニューのリソースを取得して設定するだけでよいと思いました。

ただし、写真からわかるように、奇妙な結果が得られます-コンテキストメニューがグリッド全体をカバーしているようです!

ここに画像の説明を入力

    private void OnDataGridLoaded(object sender, RoutedEventArgs e)
    {
        _dataContext = (ActivityCollectionViewModel)DataContext;

        IsSynchronizedWithCurrentItem = true;
        Style = (Style)FindResource(GRID_STYLE_NAME);

        _AddColumns();

        var timeSheetColumns = Columns.Cast<TimesheetGridColumn>();
        foreach (var col in timeSheetColumns)
        {
            col.SetHeader();
            col.SetCellStyle(this);
            col.SetBinding();
        }

        if(DesignerProperties.GetIsInDesignMode(this)) {
            // just so the designer doesn't hit a null reference on the data context
            ItemsSource = new ObservableCollection<ActivityViewModel>();
        }
        else {
            // ok, we have a runtime data context to work with
            ItemsSource = _dataContext.ActivityVms;
            InputBindings.AddRange(_GetKeyBindings());
            ContextMenu = _GetContextMenu();
            ContextMenu.Style = (Style)FindResource("ContextMenuItemStyle");
        }
    }


    private void OnDataGridLoaded(object sender, RoutedEventArgs e)
    {
        _dataContext = (ActivityCollectionViewModel)DataContext;

        IsSynchronizedWithCurrentItem = true;
        Style = (Style)FindResource(GRID_STYLE_NAME);

        _AddColumns();

        var timeSheetColumns = Columns.Cast<TimesheetGridColumn>();
        foreach (var col in timeSheetColumns)
        {
            col.SetHeader();
            col.SetCellStyle(this);
            col.SetBinding();
        }

        if(DesignerProperties.GetIsInDesignMode(this)) {
            // just so the designer doesn't hit a null reference on the data context
            ItemsSource = new ObservableCollection<ActivityViewModel>();
        }
        else {
            // ok, we have a runtime data context to work with
            ItemsSource = _dataContext.ActivityVms;
            InputBindings.AddRange(_GetKeyBindings());
            ContextMenu = _GetContextMenu();
            ContextMenu.Style = (Style)FindResource("ContextMenuItemStyle");
        }
    }

最新のアップデート

この SO 投稿ごとにバインドを相対的にしようとしましたが、サイコロはありませんでした。コマンドが更新されました。つまり、正しいセルで実行されましたが、どのセルであるかをテキストに反映させることができませんでした。最終的に、以下のようにオンザフライでコンテキスト メニューを作成することにしました。私はもっ​​とうまくやれるはずだったようですが、うまくいきます。

エルノに答えを出して締めくくります。

    private void OnCurrentCellChanged(object sender, EventArgs e)
    {
        if (ReferenceEquals(null, sender)) return;
        var grid = (DataGrid)sender;
        var selectedActivity = (ActivityViewModel)grid.CurrentItem;
        if (ReferenceEquals(selectedActivity, null)) return;

        if (_isEditableDayOfTheWeekColumn(grid.CurrentColumn))
        {
            var dowCol = (DayOfTheWeekColumn)grid.CurrentColumn;
            var index = Convert.ToInt32(dowCol.DowIndex);
            selectedActivity.SetSelectedAllocationVm(index);
        }
        else
        {
            selectedActivity.SetSelectedAllocationVm(-1);
        }
        var commands = selectedActivity
            .AllCommands
            .Select(vmMenuItem => vmMenuItem.Command.ToMenuItem());
        var cm = new ContextMenu();
        foreach (var item in commands)
        {
            //item.SetResourceReference(StyleProperty, "ContextMenuItemStyle");
            cm.Items.Add(item);
        }
        grid.ContextMenu = cm;
    }
4

1 に答える 1

1

私の推測では、コードでもスタイルを使用したいと考えています。Style クラスのインスタンスを作成し、そのプロパティ (バインディングを含む) を設定して、ツリーの Resources プロパティに追加するだけです。

次に、生成されたメニュー項目でスタイルを使用します。

于 2011-04-02T18:30:33.010 に答える