0

次のコードに問題があります。コレクションにバインドされている TreeView コントロールがあります。TreeView には、目的の結果が取り込まれます。ただし、「IsSelected」プロパティと ContextMenu のクリック コマンドは起動しません。以下は XAML コードです。

    <UserControl x:Class="Plan.Views.PadView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:v="clr-namespace:Planner.Views"
             xmlns:vm="clr-namespace:Planner.ViewModels"
    <Grid>
        <StackPanel Orientation="Vertical">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" OpacityMask="#FFECF5F5">
                    <TreeView ItemsSource="{Binding Pads}" Name="tree_View" Width="190">
                        <TreeView.ItemContainerStyle >
                            <Style TargetType="{x:Type TreeViewItem}">
                                <Setter Property="IsSelected" Value="{Binding WellPadViewModel.IsSelected}" />
                                <Setter Property="ContextMenu">
                                    <Setter.Value>
                                        <ContextMenu>
                                            <MenuItem Header="Rename" Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeView}}, Path=DataContext.RenameCommand}"  />
                                        </ContextMenu>
                                    </Setter.Value>
                                </Setter>
                                <Style.Triggers>
                                    <Trigger Property="IsSelected" Value="True">
                                    </Trigger>
                                </Style.Triggers>
                            </Style>
                        </TreeView.ItemContainerStyle >
                        <TreeView.ItemTemplate>
                            <HierarchicalDataTemplate ItemsSource="{Binding Members}">
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="{Binding Name}" >
                                        <TextBlock.InputBindings>
                                                <KeyBinding Key="F2"  Command="{Binding RenameCommand}"/>
                                            </TextBlock.InputBindings>
                                    </TextBlock>
                                </StackPanel>
                         </HierarchicalDataTemplate>
                        </TreeView.ItemTemplate>
                    </TreeView>
                </StackPanel>
            </Grid>
        </StackPanel>
    </Grid>
</UserControl>

そして、ここに私のViewModelがあります

using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
using System.ComponentModel;
using WPFApplication;

namespace FieldPlanner.ViewModels
{
    public class PlanViewModel : BaseViewModel
    {
        Collection<Pads> pads = new Collection<Pads>();
        public PlanViewModel()
        {
            IsSelected = true;
            pads = new Collection<Pad>();
        }

        private ICommand _RenameCommand;

        public ICommand RenameCommand
        {
            get
            {
                if (_RenameCommand == null)
                {
                    _RenameCommand = new RelayCommand1((o) =>
                    {
                        // Your logic should go here
                        MessageBox.Show("Please rename me");
                    });
                }
                return _RenameCommand;
            }
        }

        public ObservableCollection<PadInfo> Members { get; set; }

        private static object _selectedItem = null;
        // This is public get-only here but you could implement a public setter which also selects the item.
        // Also this should be moved to an instance property on a VM for the whole tree, otherwise there will be conflicts for more than one tree.
        public static object SelectedItem
        {
            get { return _selectedItem; }
            private set
            {
                if (_selectedItem != value)
                {
                    _selectedItem = value;
                    OnSelectedItemChanged();
                }
            }
        }

        public static void OnSelectedItemChanged()
        {
            // Raise event / do other things
        }

        private bool _isSelected;
        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (_isSelected != value)
                {
                    _isSelected = value;
                    OnPropertyChanged("IsSelected");
                    if (_isSelected)
                    {
                        SelectedItem = this;
                    }
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            var handler = this.PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    /// <summary>
    /// Class to hold the Pads info for a tree
    /// </summary>
    public class Pad
    {
        /// <summary>
        /// Default Constructor
        /// </summary>
        public Pad()
        {
            this.Members = new ObservableCollection<PadInfo>();
        }

        /// <summary>
        /// Name of the pad
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Members of the pad
        /// </summary>
        public ObservableCollection<PadInfo> Members { get; set; }
    }

    /// <summary>
    /// Class to hold the well and slot IDs snapped to a pad
    /// </summary>
    public class PadInfo
    {
        /// <summary>
        /// Slot ID
        /// </summary>
        public string SlotID { get; set; }

        /// <summary>
        /// Well ID
        /// </summary>
        public string WellID { get; set; }
    }

    public class RelayCommand1 : ICommand
    {
        #region Fields
        readonly Action<object> _execute;
        readonly Predicate<object> _canExecute;
        #endregion // Fields

        #region Constructors
        public RelayCommand1(Action<object> execute)
            : this(execute, null)
        {
        }
        public RelayCommand1(Action<object> execute, Predicate<object> canExecute)
        {
            if (execute == null)
                throw new ArgumentNullException("execute");

            _execute = execute;
            _canExecute = canExecute;
        }
        #endregion // Constructors
        #region ICommand Members
        // [DebuggerStepThrough]
        public bool CanExecute(object parameter)
        {
            return _canExecute == null ? true : _canExecute(parameter);
        }
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        public void Execute(object parameter)
        {
            _execute(parameter);
        }

        #endregion // ICommand Members
    }
}

問題を特定するにはどうすればよいですか?

4

2 に答える 2

0

2 つの問題があります。

選択済み:

<Setter Property="IsSelected" Value="{Binding WellPadViewModel.IsSelected}" />

TreeViewItem では、DataContext は Pad のインスタンスに設定され、Pad にはプロパティ IsSelected がありません。次のようにする必要があります。

<Setter Property="IsSelected" Value="{Binding DataContext.IsSelected, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}" />

ContextMenu の問題はもっと深刻です。ContextMenu は VisualTree にないため、RelativeSource にバインドできません。解決策はこちらWPF 相対ソース - 参照によるバインディングのソースが見つかりません

よろしくお願いします

于 2013-07-08T11:20:58.123 に答える
0

DataTemplate の Tag プロパティを TreeViewItem に設定してください。私はこのようなsthを持っています:

<DataTemplate>
    <Grid Width="270" Height="20" Tag="{Binding DataContext, RelativeSource = {RelativeSource AncestorType={x:Type UserControl}}}">
          ...
    <Grid.ContextMenu>
          <ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">
                <MenuItem Header="Edit">
                    <i:Interaction.Triggers>
                         <i:EventTrigger EventName="Click">
                              <command:EventToCommand Command="{Binding Tag.YOURCOMMAND}"/>
                         </i:EventTrigger>
                     </i:Interaction.Triggers>
                  </MenuItem>
            </ContextMenu>
        </Grid.ContextMenu>
    </Grid>
</DataTemplate>

それはうまくいくはずです。

于 2013-07-10T08:34:59.757 に答える