Quantcast
Channel: patterns & practices: Prism
Viewing all articles
Browse latest Browse all 1878

New Post: (WPF4+ Prism4) How to use InvokeCommandAction ?

$
0
0
Federico,

My Goal:
Implement a WPF TreeView, it will response when user browse to any leaf TreeViewItem of the TreeView.

My Project QTVB compose of following tree files.

(1) MainWindow.xaml
<Window x:Class="QTVB.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        Title="MainWindow" Height="350" Width="525">
    <DockPanel>
        <Button Content="Setup" DockPanel.Dock="Top" Command="{Binding SetupCommand}" />
        <TextBox Text="{Binding Message}" DockPanel.Dock="Top"/>
        <TreeView Name="root" ItemsSource="{Binding Leafs}">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource = "{Binding Path=nodes}">
                    <TextBlock Text="{Binding Path=Name}" >
                        <i:Interaction.Triggers>
                            <i:EventTrigger EventName="MouseDown" >
                                <i:InvokeCommandAction Command="{Binding ElementName=root,Path= DataContext.FooCommand}" CommandParameter="{Binding }"  />
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
                    </TextBlock>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </DockPanel>
</Window>
(2) MainWindow.xaml.cs
namespace QTVB
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainViewModel();
        }
    }
}
(3) MainViewModel.cs
namespace QTVB
{
    public class MainViewModel:NotificationObject
    {
        public const string LeafsPropertyName = "Leafs";
        private ObservableCollection<Leaf> _Leafs = new ObservableCollection<Leaf>();
        public ObservableCollection<Leaf> Leafs
        {
            get
            {
                return _Leafs;
            }
            set
            {
                if (_Leafs == value)
                {
                    return;
                }
                _Leafs = value;
                RaisePropertyChanged(LeafsPropertyName);
            }
        }
        public const string MessagePropertyName = "Message";
        private string _Message = string.Empty;
        public string Message
        {
            get
            {
                return _Message;
            }
            set
            {
                if (_Message == value)
                {
                    return;
                }
                _Message = value;
                RaisePropertyChanged(MessagePropertyName);
            }
        }
        private DelegateCommand<Leaf> _FooCommand;
        public DelegateCommand<Leaf> FooCommand
        {
            get
            {
                return _FooCommand
                    ?? (_FooCommand = new DelegateCommand<Leaf>(
                                          (p) =>
                                          {
                                              if (p.IsLeaf) Message = p.Name;
                                          }));
            }
        }
        private DelegateCommand _SetupCommand;
        public DelegateCommand SetupCommand
        {
            get
            {
                return _SetupCommand
                    ?? (_SetupCommand = new DelegateCommand(
                                          () =>
                                          {
                                              ConstructLeafs();
                                          }));
            }
        }
        public MainViewModel()
        {
            ConstructLeafs();
        }
        public void ConstructLeafs()
        {
            Leafs.Clear();
            Leafs.Add(new Leaf("Stem1", false));
            Leafs.Add(new Leaf("Stem2", false));
            Leafs[0].nodes.Add(new Leaf("leaf11", true));
            Leafs[0].nodes.Add(new Leaf("leaf12", true));
            Leafs[0].nodes.Add(new Leaf("leaf13", true));
            Leafs[1].nodes.Add(new Leaf("leaf21", true));
            Leafs[1].nodes.Add(new Leaf("leaf22", true));
        }
    }
    public class Leaf : NotificationObject
    {
        public const string NamePropertyName = "Name";
        private string _Name = string.Empty;
        public string Name
        {
            get
            {
                return _Name;
            }
            set
            {
                if (_Name == value)
                {
                    return;
                }
                _Name = value;
                RaisePropertyChanged(NamePropertyName);
            }
        }
        public const string IsLeafPropertyName = "IsLeaf";
        private bool _IsLeaf = false;
        public bool IsLeaf
        {
            get
            {
                return _IsLeaf;
            }
            set
            {
                if (_IsLeaf == value)
                {
                    return;
                }
                _IsLeaf = value;
                RaisePropertyChanged(IsLeafPropertyName);
            }
        }
        public ObservableCollection<Leaf> nodes
        {
            get;
            set;
        }
        public Leaf(string name,bool isleaf)
        {
            Name = name;
            IsLeaf = isleaf;
            nodes = new ObservableCollection<Leaf>();
        }
    }
}
In this project QTVB , user can click at the leaf TreeViewItem to let FooCommand execute as expected. But when user use arrow key to navigate among leaf TreeViewItem, nothing happens.

So I create project QTVB2. In QTVB2, the only difference is the file MainWindow.xaml.
(1) MainWindow.xaml
<Window x:Class="QTVB.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        Title="MainWindow" Height="350" Width="525">
    <DockPanel>
        <Button Content="Setup" DockPanel.Dock="Top" Command="{Binding SetupCommand}" />
        <TextBox Text="{Binding Message}" DockPanel.Dock="Top"/>
        <TreeView Name="root" ItemsSource="{Binding Leafs}" >
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectedItemChanged" >
                    <i:InvokeCommandAction Command="{Binding FooCommand}" CommandParameter="{Binding ElementName=root, Path=SelectedValue }"  />
                </i:EventTrigger>
            </i:Interaction.Triggers>
           <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource = "{Binding Path=nodes}">
                    <TextBlock Text="{Binding Path=Name}" >
                    </TextBlock>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </DockPanel>
</Window>
In project QTVB2, when user browse to leaf TreeViewItem using arrow key, FooCommand execute as expected.
But after browse to some leaf, if user click Setup button to execute SetupCommand, exception "can not convert object of type System.Windows.Controls.TreeViewItem to type QTVB.Leaf" throws
How to Fix it ? Thanks.

Best Regards
HJY

Viewing all articles
Browse latest Browse all 1878

Trending Articles