首页 > 其他分享 >WPF.Basic.ICommand使用

WPF.Basic.ICommand使用

时间:2023-05-17 14:00:14浏览次数:42  
标签:ICommand 控件 gt lt Grid Basic Command WPF public

WPF 命令绑定的各种方式

引言

在WPF开发过程中,不得不学习的就是MVVM模式。但是在MVVM中又绕不开命令(Command)的使用。下面通过几种方式介绍我了解的WPF命令绑定方式。

如何使用

控件继承ICommand接口,直接使用Command

首先通过这里简单介绍Command在MVVM中的使用。

ViewModel类

// using System.ComponentModel;
// using System.Runtime.CompilerServices;

MainViewModel

	/// <summary>
    /// Interactive logic for MainWindow
    /// </summary>
    public class MainViewModel : INotifyPropertyChanged
    {
        public MainViewModel()
        {
            SignInCommand = new RelayCommand(() =>
            {
                MessageBox.Show($"Hello {Username},welcome to Melphily's world");
            });
        }
        private string username;
    /// &lt;summary&gt;
    /// User name
    /// &lt;/summary&gt;
    public string Username
    {
        get { return username; }
        set
        {
            username = value;
            RaisePropertyChanged();
        }
    }

    /// &lt;summary&gt;
    /// Sign in command
    /// &lt;/summary&gt;
    public ICommand SignInCommand { get; private set; }

    #region Notify Handler

    public event PropertyChangedEventHandler PropertyChanged = (sender, e) =&gt; { };

    public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

Command类

// using System.Windows.Input;

RelayCommand

    /// <summary>
    /// the command without input parameter
    /// </summary>
    public class RelayCommand : ICommand
    {
        public event EventHandler CanExecuteChanged = (sender, e) => { };
    private Action mAction;

    public RelayCommand(Action action)
    {
        this.mAction = action;
    }

    public bool CanExecute(object parameter)
    {
        // Always allow the action can execute.
        return true;
    }

    public void Execute(object parameter)
    {
        // Take action
        mAction.Invoke();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

View类

MainWindow.xaml

<Window x:Class="Melphily.MainWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Melphily"
        mc:Ignorable="d"
        Title="Melphily" Height="450" Width="800">
    <Grid Background="Black">
        <Border VerticalAlignment="Center" Width="300" Padding="20 60" Background="White" CornerRadius="5">
            <Border.Effect>
                <DropShadowEffect Color="#FF924AC3"/>
            </Border.Effect>
            <Border.BorderBrush>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF22B5CD" Offset="1"/>
                    <GradientStop Color="#FFB92020"/>
                </LinearGradientBrush>
            </Border.BorderBrush>
            <StackPanel >
                <TextBlock Text="Sign In" TextAlignment="Center" FontSize="22">
                    <TextBlock.Foreground>
                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                            <GradientStop Color="#FF310F89" Offset="0"/>
                            <GradientStop Color="#FF26C6EA" Offset="1"/>
                        </LinearGradientBrush>
                    </TextBlock.Foreground>
                </TextBlock>
                <TextBlock Text="Username" Margin="0 20 0 0"/>
                <TextBox Text="{Binding Username}" />
            &lt;Button Command="{Binding SignInCommand}" Content="Sign In" Margin="0 20 0 0"/&gt;
        &lt;/StackPanel&gt;
    &lt;/Border&gt;
&lt;/Grid&gt;

</Window>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

MainWindow.xaml.cs

	/// <summary>
    /// Interactive logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        // Bind the Binding source to the DataContext
        DataContext = new MainViewModel();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

至此,MVVM的简单应用就完成了。这里面简单实现了输入用户名登陆,在登陆(Sign In)操作时,使用了命令绑定的形式****,在ViewModel类(MainViewModel)接收命令,并做相应的处理。

运行效果:

在这里插入图片描述

扩展使用

上面通过较为完整的实例展示了MVVM模式中的Command绑定使用。但是一些WPF控件(例如ListBox)并不支持Command命令绑定。下面我们通过几种方式讨论如何解决,以ListBox举例。

使用InputBinding

Model

MusicItemModel.cs

public class MusicItemModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Singer { get; set; }
    public MusicItemModel()
    {
        SelectedCommand = new RelayCommandWithParameter(p =&gt;
        {
            MessageBox.Show($"Selected music is {Name} Singed by {Singer},the Id is {p}");
        });
    }

    /// &lt;summary&gt;
    /// Select command
    /// &lt;/summary&gt;
    public ICommand SelectedCommand { get; private set; }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

Command

RelayCommandWithParameter.cs

	/// <summary>
    /// the command without input parameter
    /// </summary>
    public class RelayCommandWithParameter : ICommand
    {
        public event EventHandler CanExecuteChanged = (sender, e) => { };
    private Action&lt;object&gt; mActionWithParameter;

    public RelayCommandWithParameter(Action&lt;object&gt; action)
    {
        this.mActionWithParameter = action;
    }

    public bool CanExecute(object parameter)
    {
        // Always allow the action can execute.
        return true;
    }

    public void Execute(object parameter)
    {
        // Take action
        mActionWithParameter.Invoke(parameter);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

View Model

MusicListViewModel.cs

 /// <summary>
    /// Interactive logic for MusicListPage
    /// </summary>
    public class MusicListViewModel : INotifyPropertyChanged
    {
    public MusicListViewModel()
    {
        Musics = new ObservableCollection&lt;MusicItemModel&gt;()
        {
            new MusicItemModel(){ Id=1, Name="甜甜的", Singer="周杰伦"},
            new MusicItemModel(){ Id=1, Name="说好的幸福呢", Singer="周杰伦"},
            new MusicItemModel(){ Id=1, Name="彩虹", Singer="周杰伦"},
            new MusicItemModel(){ Id=1, Name="一路向北", Singer="周杰伦"},
            new MusicItemModel(){ Id=1, Name="Married You", Singer="布鲁诺·马尔斯"},
        };
    }

    private ObservableCollection&lt;MusicItemModel&gt; musics;

    public ObservableCollection&lt;MusicItemModel&gt; Musics
    {
        get { return musics; }
        set { musics = value; RaisePropertyChanged(); }
    }

    #region Notify Handler

    public event PropertyChangedEventHandler PropertyChanged = (sender, e) =&gt; { };

    public void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

View

MusicListPage.xaml.cs

	/// <summary>
    /// Interactive logic for MusicListPage.xaml 
    /// </summary>
    public partial class MusicListPage : Page
    {
        public MusicListPage()
        {
            InitializeComponent();
            DataContext = new MusicListViewModel();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

MusicListPage.xaml

<Page x:Class="Melphily.MusicListPage"
      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:local="clr-namespace:Melphily"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Title="MusicListPage">
&lt;Grid&gt;
    &lt;ListBox ItemsSource="{Binding Musics}"&gt;
        &lt;ListBox.ItemTemplate&gt;
            &lt;DataTemplate &gt;
                &lt;Grid&gt;
                    &lt;Grid.InputBindings&gt;
                        &lt;MouseBinding MouseAction="LeftClick" Command="{Binding SelectedCommand}" CommandParameter="{Binding Id}"/&gt;
                    &lt;/Grid.InputBindings&gt;
                    &lt;Grid.ColumnDefinitions&gt;
                        &lt;ColumnDefinition Width="300"/&gt;
                        &lt;ColumnDefinition Width="*"/&gt;
                    &lt;/Grid.ColumnDefinitions&gt;
                    &lt;TextBlock Grid.Column="0" Text="{Binding Name}"/&gt;
                    &lt;TextBlock Grid.Column="1" Text="{Binding Singer}"/&gt;
                &lt;/Grid&gt;
            &lt;/DataTemplate&gt;
        &lt;/ListBox.ItemTemplate&gt;
    &lt;/ListBox&gt;
&lt;/Grid&gt;

</Page>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

命令绑定是使用Grid控件的InputBinding实现的。

<Grid.InputBindings>
	<MouseBinding MouseAction="LeftClick" Command="{Binding SelectedCommand}" CommandParameter="{Binding Id}"/>
</Grid.InputBindings>
  • 1
  • 2
  • 3

在这里插入图片描述

使用System.Windows.Interactivity.dll

呈现的内容和上面一样,只需要修改MusicListPage.xaml中的命令绑定即可。

System.Windows.Interactivity.dll这个时微软后期提供的。

1.将System.Windows.Interactivity.dll引入到项目中。

在这里插入图片描述

在这里插入图片描述

2.XAML中声明

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

3.XAML中使用

						<i:Interaction.Triggers>
                            <i:EventTrigger EventName="MouseLeftButtonDown">
                                <i:InvokeCommandAction Command="{Binding SelectedCommand}" CommandParameter="{Binding Id}"/>
                            </i:EventTrigger>
                        </i:Interaction.Triggers>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

MusicListPage.xaml

<Page x:Class="Melphily.MusicListPage"
      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:local="clr-namespace:Melphily"
      xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Title="MusicListPage">
&lt;Grid&gt;
    &lt;ListBox ItemsSource="{Binding Musics}"&gt;
        &lt;ListBox.ItemTemplate&gt;
            &lt;DataTemplate &gt;
                &lt;Grid&gt;
                    &lt;!--&lt;Grid.InputBindings&gt;
                        &lt;MouseBinding MouseAction="LeftClick" Command="{Binding SelectedCommand}" CommandParameter="{Binding Id}"/&gt;
                    &lt;/Grid.InputBindings&gt;--&gt;
                    &lt;i:Interaction.Triggers&gt;
                        &lt;i:EventTrigger EventName="MouseLeftButtonDown"&gt;
                            &lt;i:InvokeCommandAction Command="{Binding SelectedCommand}" CommandParameter="{Binding Id}"/&gt;
                        &lt;/i:EventTrigger&gt;
                    &lt;/i:Interaction.Triggers&gt;
                    &lt;Grid.ColumnDefinitions&gt;
                        &lt;ColumnDefinition Width="300"/&gt;
                        &lt;ColumnDefinition Width="*"/&gt;
                    &lt;/Grid.ColumnDefinitions&gt;
                    &lt;TextBlock Grid.Column="0" Text="{Binding Name}"/&gt;
                    &lt;TextBlock Grid.Column="1" Text="{Binding Singer}"/&gt;
                &lt;/Grid&gt;
            &lt;/DataTemplate&gt;
        &lt;/ListBox.ItemTemplate&gt;
    &lt;/ListBox&gt;
&lt;/Grid&gt;

</Page>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

在这里插入图片描述

自定义模板使用含有ICommand接口的控件传递命令

对于没有继承ICommand接口的控件,可以重定义控件的模板,并在模板中加入可以使用Command绑定的控件例如Button来实现命令的绑定。

使用上面的示例,只修改数据模板,如下所示。

MusicListPage.xaml

<Page x:Class="Melphily.MusicListPage"
      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:local="clr-namespace:Melphily"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Title="MusicListPage">
&lt;Grid&gt;
    &lt;ListBox ItemsSource="{Binding Musics}"&gt;
        &lt;ListBox.ItemTemplate&gt;
            &lt;DataTemplate &gt;
                &lt;Grid&gt;
                    &lt;Grid.ColumnDefinitions&gt;
                        &lt;ColumnDefinition Width="300"/&gt;
                        &lt;ColumnDefinition Width="*"/&gt;
                    &lt;/Grid.ColumnDefinitions&gt;
                    &lt;TextBlock Grid.Column="0" Text="{Binding Name}"/&gt;
                    &lt;TextBlock Grid.Column="1" Text="{Binding Singer}"/&gt;

                    &lt;!-- 可以绑定命令的控件 --&gt;
                    &lt;Button Grid.ColumnSpan="2" 
                            Command="{Binding SelectedCommand}" 
                            CommandParameter="{Binding Id}"
                            Foreground="Transparent" Background="Transparent" /&gt;
                &lt;/Grid&gt;
            &lt;/DataTemplate&gt;

        &lt;/ListBox.ItemTemplate&gt;
    &lt;/ListBox&gt;
&lt;/Grid&gt;

</Page>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

虽然这种方式比较简单粗暴,但由于是直接在模板上面操作,所有控件是否有焦点变得非常重要了,还有就是需要隐藏控件的一些不需要显示的样式。

样式没设置好,会出现意想不到的情况。如下:

在这里插入图片描述

自定义模板使用用户控件(UserControl)【添加Command依赖属性】传递命令

鉴于上面自定义模板使用含有ICommand接口的控件传递命令的方式存在的一些弊端,我们可以自定义带有命令的控件来解决不便利的地方。

1.自定义CommandControl控件

CommandControl.xaml

<UserControl x:Class="Melphily.UiCore.CommandControl"
             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:local="clr-namespace:Melphily.UiCore"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             Background="Transparent">
</UserControl>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

CommandControl.xaml.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace Melphily.UiCore
{
/// <summary>
/// CommandControl.xaml 的交互逻辑
/// </summary>
public partial class CommandControl : UserControl
{
public CommandControl()
{
InitializeComponent();
MouseLeftButtonDown += onm ouseLeftButtonDown;
}
private void onm ouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
{
if (Command != null)
{
if (Command.CanExecute(CommandParameter))
{
Command.Execute(CommandParameter);
}
}
}

    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof(ICommand),
            typeof(CommandControl),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public static readonly DependencyProperty CommandParameterProperty =
        DependencyProperty.Register("CommandParameter", typeof(object),
            typeof(CommandControl),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));

    public object CommandParameter
    {
        get { return (object)GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }
}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

2.在模板中使用CommandControl

MusicListPage.xaml

<Page x:Class="Melphily.MusicListPage"
      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:local="clr-namespace:Melphily"
      xmlns:uicore="clr-namespace:Melphily.UiCore"
      xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Title="MusicListPage">
&lt;Grid&gt;
    &lt;ListBox ItemsSource="{Binding Musics}"&gt;
        &lt;ListBox.ItemTemplate&gt;
            &lt;DataTemplate &gt;
				&lt;uicore:CommandControl Command="{Binding SelectedCommand}"
                                       CommandParameter="{Binding Id}"&gt;

                    &lt;Grid&gt;
                        &lt;Grid.ColumnDefinitions&gt;
                            &lt;ColumnDefinition Width="300"/&gt;
                            &lt;ColumnDefinition Width="*"/&gt;
                        &lt;/Grid.ColumnDefinitions&gt;
                        &lt;TextBlock Grid.Column="0" Text="{Binding Name}"/&gt;
                        &lt;TextBlock Grid.Column="1" Text="{Binding Singer}"/&gt;
                    &lt;/Grid&gt;
                    
				&lt;/uicore:CommandControl&gt;
            &lt;/DataTemplate&gt;

        &lt;/ListBox.ItemTemplate&gt;
    &lt;/ListBox&gt;
&lt;/Grid&gt;

</Page>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

由于CommandControl是一个透明的控件,因此不用考虑样式的问题,可以直接使用。其次它是内容控件,因此该控件是始终存在焦点。

但是,如果将该控件作为模板(ControlTemplate/DataTemplate)时,发现无法对容器内的控件设置名称,因此,在设置样式模板时局限性会很大。

自定义模板使用自定义控件(CustomControl)【添加Command依赖属性】传递命令

鉴于用户控件带来的弊端,我们依然可以使用自定义控件(CustomControl)来解决。

创建一个自定义控件:

在项目中点击添加–》新建项

然后找到“CustomControl”或者“WPF自定义控件”,设置好名称,点击创建。

创建之后首先会存在一个对应.cs文件,然后会自动创建一个Theme(主题)文件夹,并创建一个Generic.xaml文件(通用样式文件)。

接下来我们编写自定义控件

1.加入我们的命令依赖属性和相关处理事件。

CommandControl.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace Deamon.UiCore
{
/// <summary>
/// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
///
/// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
/// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
/// 元素中:
///
/// xmlns:MyNamespace="clr-namespace:Deamon.UiCore"
///
///
/// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
/// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
/// 元素中:
///
/// xmlns:MyNamespace="clr-namespace:Deamon.UiCore;assembly=Deamon.UiCore"
///
/// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
/// 并重新生成以避免编译错误:
///
/// 在解决方案资源管理器中右击目标项目,然后依次单击
/// “添加引用”->“项目”->[浏览查找并选择此项目]
///
///
/// 步骤 2)
/// 继续操作并在 XAML 文件中使用控件。
///
/// <MyNamespace:CommandControl/>
///
/// </summary>
public class CommandControl : ContentControl
{
static CommandControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CommandControl), new FrameworkPropertyMetadata(typeof(CommandControl)));
}
public CommandControl()
{
MouseLeftButtonDown += CommandControlCC_MouseLeftButtonDown;
}

    private void CommandControlCC_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (Command != null)
        {
            if (Command.CanExecute(CommandParameter))
            {
                Command.Execute(CommandParameter);
            }
        }
    }

    private void onm ouseLeftButtonDown(object sender, MouseButtonEventArgs mouseButtonEventArgs)
    {
        if (Command != null)
        {
            if (Command.CanExecute(CommandParameter))
            {
                Command.Execute(CommandParameter);
            }
        }
    }

    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof(ICommand),
            typeof(CommandControl),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public static readonly DependencyProperty CommandParameterProperty =
        DependencyProperty.Register("CommandParameter", typeof(object),
            typeof(CommandControl),
            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));

    public object CommandParameter
    {
        get { return (object)GetValue(CommandParameterProperty); }
        set { SetValue(CommandParameterProperty, value); }
    }
}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92

注释是默认加上的,是用来引导你如何设计和使用该自定义控件。默认情况下,自定义控件是继承自Control类的,因为我们的命令控件是需要包裹其它控件,所以直接继承ContentControl会减少我们对内容设计的逻辑代码。(PS:如果不这么做也可以自己添加Content属性,然后再面板中使用ContentPresenter将Content显示到界面上。)

2.在Generic.xaml文件中修改控件默认样式

Generic.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Deamon"
    xmlns:uicore="clr-namespace:Deamon.UiCore"
    >
    <!-- 带命令绑定的内容控件 -->
    <Style TargetType="{x:Type uicore:CommandControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type uicore:CommandControl}">
                    <ContentControl>
                        <ContentPresenter/>
                    </ContentControl>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

ContentPresenter默认情况下已经将Content属性绑定到了改控件上,如果是其它控件,需要具体了解(绑定、样式、模板等)相关知识。

3.在模板中使用CommandControl

MusicListPage.xaml

<Page x:Class="Melphily.MusicListPage"
      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:local="clr-namespace:Melphily"
      xmlns:uicore="clr-namespace:Melphily.UiCore"
      xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
      mc:Ignorable="d" 
      d:DesignHeight="450" d:DesignWidth="800"
      Title="MusicListPage">
&lt;Grid&gt;
    &lt;ListBox ItemsSource="{Binding Musics}"&gt;
        &lt;ListBox.ItemTemplate&gt;
            &lt;DataTemplate &gt;
				&lt;uicore:CommandControl Command="{Binding SelectedCommand}"
                                       CommandParameter="{Binding Id}"&gt;

                    &lt;Grid&gt;
                        &lt;Grid.ColumnDefinitions&gt;
                            &lt;ColumnDefinition Width="300"/&gt;
                            &lt;ColumnDefinition Width="*"/&gt;
                        &lt;/Grid.ColumnDefinitions&gt;
                        &lt;TextBlock Grid.Column="0" Text="{Binding Name}"/&gt;
                        &lt;TextBlock Grid.Column="1" Text="{Binding Singer}"/&gt;
                    &lt;/Grid&gt;
                    
				&lt;/uicore:CommandControl&gt;
            &lt;/DataTemplate&gt;

        &lt;/ListBox.ItemTemplate&gt;
    &lt;/ListBox&gt;
&lt;/Grid&gt;

</Page>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

使用方式和UserControl一模一样,只是控件的定义方式不一样而已。

标签:ICommand,控件,gt,lt,Grid,Basic,Command,WPF,public
From: https://www.cnblogs.com/HomeSapiens/p/17408558.html

相关文章

  • 5、Nginx 常见模块 auth_basic:实现账户认证功能
    Nginx账户认证功能由ngx_http_auth_basic_module模块提供此功能官方帮助:http://nginx.org/en/docs/http/ngx_http_auth_basic_module.html语法格式:Syntax: auth_basic_user_filefile;Default: —Context: http,server,location,limit_except范例:authbasic提......
  • 大型源码C# MES WPF CS/BS两套 1, 整体程序由WPF(c#)开发; 2
    大型源码C#MESWPFCS/BS两套1,整体程序由WPF(c#)开发;2,各个文档齐全;3,需要您对WPF和程序架构有比较深入理解;4,包含服务程序;5,包含SCADA数据采集系统;6,包含数据看板;7,包含各种组件;8,包含完整的各个处理脚本。9,由多个产品线程序组成。10,数据库的使用。11,远程服务器的调用......
  • ERP MES 两套系统源代码 WPF AGV C# WPF开发。 A,WPF MES 上位机产线
    ERPMES两套系统源代码WPFAGVC#WPF开发。A,WPFMES上位机产线执行系统。1,完整纯源代码;2,AGV自动调度;3,SQLSERVER数据库。带附加文件。4,WPF各种技术应用。5,数据库技术应用。6,DTU数据传输。7,TCPIPSOCKET技术应用。8,EXCEL数据查询与导出。9,各种库位的管理。10,重要是多线......
  • C#WPF大数据电子看板源码 WPF智慧工厂数据平台 1, 提供
    C#WPF大数据电子看板源码WPF智慧工厂数据平台1,提供一个智慧工厂数据平台框架。2,理解wpf的设计模式。3,学习如何绘制各种统计图。4,设计页面板块划分。5,如何在适当时候展现动画。6,提供纯源代码!有盆友问,这个是否带数据库,其实这个不是重点,重点是页面展示。数据库嘛,安装一个,连接......
  • WPF MES 上位机源码产线执行系统 C# WPF开发 1, VS2019的运
    WPFMES上位机源码产线执行系统C#WPF开发1,VS2019的运行环境;完整的WPF源代码;2,AGV自动调度;3,SQLSERVER数据库。带附加文件。4,WPF各种技术应用。5,数据库技术应用。6,DTU数据传输。7,TCPIPSOCKET技术应用。8,EXCEL数据查询与导出。9,各种库位的管理。10,重要是多线程技......
  • WPF智慧工厂数据平台 1, 提供一个智慧工厂数据平台框架。 2,
    WPF智慧工厂数据平台1,提供一个智慧工厂数据平台框架。2,理解wpf的设计模式。3,学习如何绘制各种统计图。4,设计页面板块划分。5,如何在适当时候展现动画。有盆友问,这个是否带数据库,其实这个不是重点,重点是页面展示。数据库嘛,安装一个,连接上就可以了。可以互相交流。技术无止境。......
  • WPF入门教程系列二十四——DataGrid使用示例(1)
    WPF入门教程系列目录WPF入门教程系列二——Application介绍WPF入门教程系列三——Application介绍(续)WPF入门教程系列四——Dispatcher介绍WPF入门教程系列五——Window介绍WPF入门教程系列十一——依赖属性(一)WPF入门教程系列十五——WPF中的数据绑定(一)      ......
  • WPF入门教程系列目录
    WPF入门教程系列一——基础WPF入门教程系列二——Application介绍WPF入门教程系列三——Application介绍(续)WPF入门教程系列四——Dispatcher介绍WPF入门教程系列五——Window介绍WPF入门教程系列六——布局介绍与Canvas(一)WPF入门教程系列七——布局之WrapPanel与StackP......
  • 三菱伺服MR-JE-C与三菱FX-5UPLC进行两轴CCLINK-Basic总线通信程序。
    三菱伺服MR-JE-C与三菱FX-5UPLC进行两轴CCLINK-Basic总线通信程序。控制模式:有回原点,定位控制,速度控制,力矩控制,4种模式中随意切换。赠送,:通信地址分配表,编程手册,威伦通触摸屏UI模版,伺服驱动器参数文件。ID:3689682192553998......
  • WPF 资源文件 内容换行
    在文件头加一行xml:space="preserve"内容:<system:Stringx:Key="Title">AutomaticChemiluminescence&#x0d;&#x0a;ImmunoassayAnalyzer</system:String> 页面引用:Text="{StaticResourceTitle}" ......