非常感謝您的答覆和澄清!
你給了我全部的決定權,所以我想通了。我在purpouse上添加了我的完整示例。
遵從您的建議(Ron B我&丹尼斯)我首先想了解更多關於ViewModel。
在http://msdn.microsoft.com/en-ca/magazine/dd419663.aspx下面有非靜態類的例子。因此,解決辦法是簡單地在我的用戶控件添加新的類(正好如下所示提到的網站上 - 圖3 - 一些名稱變更 - 版權屬於約什 - 史密斯joshsmithonwpf.wordpress.com):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
namespace WpfCommandControl
{
class CommandImplementation : ICommand
{
#region Fields
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
#endregion // Fields
#region Constructors
public CommandImplementation(Action<object> execute)
: this(execute, null)
{
}
public CommandImplementation(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
#endregion // Constructors
#region ICommand Members
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
}
}
然後在用戶控制 「窗口」
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
namespace WpfCommandControl
{
public partial class CommandControl : UserControl, INotifyPropertyChanged
{
#region [ Private Members ]
private bool _canActivated = false;
private int _counter = 0;
CommandImplementation _activateCommand;
#endregion
#region [ Properties ]
public int CommandCounter
{
get
{
return _counter;
}
set
{
_counter = value;
OnNotifyPropertyChanged("CommandCounter");
}
}
public bool CanActivated
{
get
{
return _canActivated;
}
set
{
_canActivated = value;
OnNotifyPropertyChanged("CanActivated");
}
}
#endregion
#region [ Property_Changed_Utilities ]
public event PropertyChangedEventHandler PropertyChanged;
private void OnNotifyPropertyChanged(String info)
{
// Note: Do not forget to add interface "INotifyPropertyChanged" to your class.
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion
# region [ Commands ]
public ICommand ActivateCommand
{
get
{
return _activateCommand;
}
}
#endregion
#region [ Constructor ]
public CommandControl()
{
InitializeComponent();
_activateCommand = new CommandImplementation(param => this.Activate(), param => this.CanActivated);
}
#endregion
#region [ Methods ]
void Activate()
{
CommandCounter++;
}
#endregion
}
}
最重要的部分:
命令被執行財產:
public ICommand ActivateCommand
{
get
{
return _activateCommand;
}
}
所以它可以確保它會返回相關命令的實際情況,這是實例化用戶控件的構造λ-表達:
public CommandControl()
{
InitializeComponent();
_activateCommand = new CommandImplementation(param => this.Activate(), param => this.CanActivated);
}
拉姆達 - 表達使得該邏輯begind連接:
param => this.Activate()
對於激活()函數至極會命令來執行被激發
void Activate()
{
CommandCounter++;
}
而且
param => this.CanActivated
用於傳遞ICommand CanExecute屬性的本地邏輯,從而使您可以控制何時可以執行該命令。
在我來說,我使用的是可以綁定到複選框的財產,但你也可以做的另一種方式......
public bool CanActivated
{
get
{
return _canActivated;
}
set
{
_canActivated = value;
OnNotifyPropertyChanged("CanActivated");
}
}
同樣是從約什 - 史密斯joshsmithonwpf.wordpress.com所示 - 我只是將其更改爲在構造函數中實例化,而不是檢查私有成員是否爲null,並在Command Property的GET部分需要時提供新實例。
其餘代碼只是執行所需的屬性和OnNotifyPropertyChanged,如MSDN上所示。
XAML很簡單 - 僅用於概念驗證。
<UserControl x:Class="WpfCommandControl.CommandControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfCommandControl"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid>
<StackPanel>
<CheckBox Content="Activate" IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Path=CanActivated}" />
<Button Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=UserControl},
Path=ActivateCommand}"
Content="Click me"
IsEnabled="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=UserControl},
Path=CanActivated}" />
<Label Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Path=CommandCounter}" IsEnabled="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Path=CanActivated}" />
</StackPanel>
</Grid>
正如你所看到的只有一個複選框 - 綁定將提供啓動按鈕的開/禁用。 點擊按鈕會觸發簡單增加計數器的命令 - 再次顯示在標籤上的綁定。
把所有在一起:
只是一個簡單的XAML格式有四個用戶控件:
<Window x:Class="CommandsTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CommandsTest"
xmlns:uctrl="clr-namespace:WpfCommandControl;assembly=WpfCommandControl"
Title="MainWindow"
Width="525"
Height="350">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<uctrl:CommandControl Grid.Row="0" Grid.Column="0" />
<uctrl:CommandControl Grid.Row="0" Grid.Column="1" />
<uctrl:CommandControl Grid.Row="1" Grid.Column="0" />
<uctrl:CommandControl Grid.Row="1" Grid.Column="1" />
</Grid>
上的每個控制觸發的命令是完全一樣的所需的元素中。
全部解決在WPF的方式 - 使用命令和綁定沒有與GUI元素的任何直接的互動,從而GUI可以不需要在後面的代碼更新的交換。
再次感謝你讓我說,也有另一種(例如安全)的方式來實現在WPF自定義命令。
我認爲這些問題將類似於依賴屬性:http://stackoverflow.com/questions/3660696/non-static-dependency-properties –
我認爲你不正確理解命令。沒有什麼能夠使命令與靜態類相關。 – Euphoric
@Euphoric:與命令相關的MSDN文檔非常糟糕,因爲它充滿了這種樣本(當命令處於靜態類時)。與此同時,作爲WPF主流的MVVM方法假定,該命令是視圖模型的一部分。我明白,爲什麼這個問題出現了。 – Dennis