Page tree
Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »

WPF版版Toolbar 支持指令框架,在WPF中使用指令有几个目的,其最主要的目的在于分离对象来调用逻辑指令,指令可以降低原始界面与行为处理之间的耦合度。
以下将演示如何在WPF应用程序中使用C1Toolbar指令。

9.1 第一部分:使用指令库

WPF 提供了预定义指令库如下:
应用指令(剪切,复制,粘贴) 导航指令(前进,后退) 媒体指令(播放,停止,暂停) 编辑指令控件指令
许多WPF控件都内置这些支持的指令,因此您可以不用编写任何代码实现它们。
以下步骤介绍了如何使用C1Toolbar实现常用的剪切板功能。

  1. 打开或创建一个新的WPF应用程序。
  2. 添加两个RowDefinitions 到默认的Grid元素,为第一行设置为自动高度,如下:

    XAML

    <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition />
    </Grid.RowDefinitions>

  3. 添加一个C1Toolbar 以填充第一行。
  4. 粘贴以下XAML并使用标签,分组和按钮来填充C1Toolbar:

    XAML

    <c1:C1Toolbar Name="c1Toolbar1" FocusManager.IsFocusScope="True">
    <c1:C1ToolbarTabControl>
    <c1:C1ToolbarTabItem Header="Home">
    <c1:C1ToolbarGroup Header="Clipboard">
    <c1:C1ToolbarButton LabelTitle="Paste"
    Command="ApplicationCommands.Paste" LargeImageSource="/Resources/paste.png" />
    <c1:C1ToolbarButton LabelTitle="Cut"
    Command="ApplicationCommands.Cut" SmallImageSource="/Resources/cut.png" />
    <c1:C1ToolbarButton LabelTitle="Copy"
    Command="ApplicationCommands.Copy" SmallImageSource="/Resources/copy.png" />
    </c1:C1ToolbarGroup>
    </c1:C1ToolbarTabItem> </c1:C1ToolbarTabControl>
    </c1:C1Toolbar>

    该标记在C1Toolbar中创建一个包含单个分组的标签,Clipboard 分组包含三个C1ToolbarButtons 并为每一个从WPF应用指令库中分配一个常用的剪切板指令,注意C1Toolbar的IsFocusScope 属性被设置为True ,这可以使C1Toolbar 跟踪其范围内所有聚焦的元素,小图和大图都可以指定给C1ToolbarButtons,尽管这些并不是必要的。
  5. C1Toolbar下添加一个TextBox 控件。
  6. 运行应用程序并观察通过点击C1ToolbarButtons以执行常用的剪切板指令(粘贴,拷贝和剪切) 。


9.2 第二部分:创建自定义指令

如果在指令库中的指令不能满足您的需求,此时您可以创建您自己的指令,您仅需通过实现ICommand接口实现自定义指令,WPF 提供了一个名为RoutedCommand(及 RoutedUICommand)的具体实现,通过元素树来定义一个指令路由。
以下步骤将介绍如何使用RoutedCommands来添加一个自定义指令到C1Toolbar

  1. 使用第一部分的示例,打开隐藏代码文件。
  2. 定义一个名为ClearCommand的RoutedCommand,该指令将用于清除页面中TextBox 的文本。

public static RoutedCommand ClearCommand = new RoutedCommand();

  1. 创建一个事件处理以定义指令逻辑。

    C#

    //执行ClearCommand逻辑 private void ExecutedClearCommand(object sender, ExecutedRoutedEventArgs e)
    { textBox1.Clear();
    }

  2. 创建另一个事件处理以决定指令是否能被执行,当一个指令不能被执行时,与指令相关联的Toolbar按钮将变成灰色并禁用。

    C#

    // 若文本框中有文本则返回true。
    private void CanExecuteClearCommand(object sender, CanExecuteRoutedEventArgs e)
    { if (textBox1.Text.Length > 0)
    {
    e.CanExecute = true; } else

    {
    e.CanExecute = false;
    }
    }
  3. 下一步,创建一个CommandBinding以关联事件处理的指令,当指令调用时,元素树将被遍历以查找

CommandBinding对象,将以下代码放到InitializeComponent 后来调用您的页面:

C#

CommandBinding customCommandBinding = new CommandBinding(ClearCommand,
ExecutedClearCommand, CanExecuteClearCommand);
// 添加CommandBinding到根元素
this.CommandBindings.Add(customCommandBinding);

  1. 在包含C1Toolbar的XAML中,在分组中添加一个新的C1ToolbarButton并名为Application
  2. 在代码中设置Command 属性为静态指令。

    XAML

    <c1:C1ToolbarGroup Header="Application">
    <c1:C1ToolbarButton LabelTitle="Clear Text" Command="{x:Static local:MainWindow.ClearCommand}" LargeImageSource="/Resources/clear.png"/> </c1:C1ToolbarGroup>

  3. 运行应用程序并观察当工具栏按钮被点击时,ClearCommand 将通过遍历元素树查找项关联的CommandBinding,如果找到则相关联的事件处理将调用您的指令逻辑并执行。


9.3 第三部分:MVVM中使用指令

指令操作是MVVM(Model-View-ViewModel)设计模式的重要部分,它将UI从业务逻辑中分离开来,WPF版版 Toolbar支持指令框架并应用于广泛使用的MVVM模式中,在MVVM设计的应用程序中,指令目标常常在ViewModel中完成,其并不是UI元素树的部分,因此,在MVVM中使用RoutedCommand并不是一个好的ICommand实现,您可以使用一个特别的实现如DelegateCommandRelayCommand,可以使您的View 绑定到非UI元素树的对象。以下步骤介绍如何使用RelayCommand 类和C1Toolbar 创建第二部分相同的自定义指令。

  1. 创建一个名为MainViewModel的新类以实现INotifyPropertyChanged 接口,该类将作为我们包含C1Toolbar View的ViewModel。


C#

class MainViewModel : System.ComponentModel.INotifyPropertyChanged
{ private string textValue = ""; public string TextValue
{ get { return textValue;
} set {
textValue = value;
OnPropertyChanged("TextValue");
} }
private RelayCommand clearCommand; public ICommand ClearCommand
{ get { if (clearCommand == null)
{ clearCommand = new RelayCommand(param => this.Clear(), param => this.CanClear()); } return clearCommand;
} }
private bool CanClear()
{ return textValue.Length > 0;
}
private void Clear()
{
TextValue = "";
} public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{ PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{ handler(this, new PropertyChangedEventArgs(propertyName));

}
}
}
该类使用RelayCommand,它是DelegateCommand轻量级的变体,两个ICommand的实现允许您将指令逻辑作为参数委托给方法进行传递,指令目标不是UI元素树的部分,RelayCommandDelegateCommand 类不是WPF框架的组成部分,且不能通过MVVM工具箱在线查找。

  1. 添加RelayCommand 类到您的项目中。

    C#

    /// <summary>
    /// 该类允许将指令逻辑作为参数委托给方法传递, /// 并使一个View绑定指令到非元素树的对象。
    /// </summary> public class RelayCommand : ICommand
    {
    #region Fields
    readonly Action<object> _execute; readonly Predicate<object> _canExecute;
    #endregion // Fields #region Constructors
    public RelayCommand(Action<object> execute)
    : this(execute, null)
    { }
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    { if (execute == null) throw new ArgumentNullException("execute");
    _execute = execute;
    _canExecute = canExecute;
    }
    #endregion // 构造函数
    #region ICommand Members
    <ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="1781b40d-c8ad-4371-8626-204fc33f1574"><ac:plain-text-body><![CDATA[ [DebuggerStepThrough] public bool CanExecute(object parameter)
    ]]></ac:plain-text-body></ac:structured-macro>
    { 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成员
    }
  2. 为了绑定到ViewModel,需要添加以下XAML 到您包含C1Toolbar 的View上方:

    XAML

    <Window.Resources>
    <local:MainViewModel x:Key="viewModel" />
    </Window.Resources>
    <Window.DataContext>
    <Binding Source="{StaticResource viewModel}"/>
    </Window.DataContext>


    添加到您ViewModel 的XAML将作为资源绑定到Window或UserControl的DataContext中。
  3. 此时添加以下工具栏分组到您在第一部分创建的C1Toolbar

    XAML

    <c1:C1ToolbarGroup Header="Application">
    <c1:C1ToolbarButton LabelTitle="Clear Text" Command="{Binding ClearCommand}"
    LargeImageSource="/Resources/delete.png"/>
    </c1:C1ToolbarGroup>


    该工具栏分组包含一个带有Command属性的C1ToolbarButton,Command绑定到ViewModel定义的ClearCommand
  4. 由于指令遵循MVVM优秀的特性,文本框的 Text 属性也应该绑定到ViewModel的值,如果我们希望在上面应用业务逻辑,则需要绑定Text 属性到ViewModel中定义的TextValue

    XAML

    <TextBox Grid.Row="1" Text="{Binding TextValue,
    UpdateSourceTrigger=PropertyChanged}" Height="23" HorizontalAlignment="Left"
    Margin="12,17,0,0" Name="textBox1" VerticalAlignment="Top" Width="165" />


    通过将UpdateSourceTrigger 设置为 PropertyChanged,在ViewModel中的TextValue属性将可以在任何时刻更新Text值,而不是只有当文本框失去焦点时。
  5. 运行应用程序并观察行为中的自定义RelayCommand


通过MVVM设计模式来降低UI与业务逻辑之间的耦合度,对于您的应用开发是非常实用的。

  • No labels