简体   繁体   中英

How to binding a Command in Style in .xaml from .cs?

Now, I'm mocking up the MessageBox. I build the Close Button in Style.Template in .xaml, but I don't know how to binding the command with CloseCommand. Whether it can bingding with System Close Command ?

.cs (define a custom control):

internal sealed class MessageBoxModule : Window
{
    #region Constructor
    static MessageBoxModule()
    {
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(MessageBoxModule),
            new FrameworkPropertyMetadata(typeof(MessageBoxModule)));
    }

    public MessageBoxModule()
    {
        WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
        AllowsTransparency = true;
        WindowStyle = System.Windows.WindowStyle.None;
        ShowInTaskbar = false;

        try
        {
            Resources.Source = new Uri(@"/Wpf.Controls;component/Themes/Generic.xaml", UriKind.Relative);
        }
        catch
        { }
...

.xaml (is a ResourceDictionary file, provide a style for MessageBoxModule):

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Wpf.Controls">
        <Style TargetType="{x:Type local:MessageBoxModule}">
            <Setter Property="Template" >
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:MessageBoxModule}">
                        <Border ...>
                            <Button x:Name="CloseButton".../>
                            ...
                        </Border>
...

see the red button , I don't know how to binding a command for it:

在此处输入图片说明

This is The Entire solution:

.cs:

internal sealed class MessageBoxModule : Window
{
    public MessageBoxModule()
    {
        InputGestureCollection inputGestures = new InputGestureCollection();
        inputGestures.Add(new KeyGesture(Key.F4, ModifierKeys.Alt));
        CloseCommand = new RoutedCommand(
            "CloseCommand",
            typeof(MessageBoxModule),
            inputGestures);
        CommandBindings.Add(new CommandBinding(CloseCommand, CloseCommandExecuted));
    }

    public static readonly DependencyProperty CloseCommandProperty =
        DependencyProperty.Register(
            "CloseCommand", 
            typeof(RoutedCommand), 
            typeof(MessageBoxModule));

    public RoutedCommand CloseCommand
    {
        get { return (RoutedCommand)GetValue(CloseCommandProperty); }
        set { SetValue(CloseCommandProperty, value); }
    }

    public void CloseCommandExecuted(object sender, ExecutedRoutedEventArgs e)
    {
        Close();
    }
}

.xaml:

<ResourceDictionary >
    <Style TargetType="{x:Type local:MessageBoxModule}">
        <Setter Property="Template" >
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:MessageBoxModule}">
                    <Border ...>
                        <Button x:Name="CloseButton" Command="{TemplateBinding CloseCommand}"/>
...

@SubmarineX

Create a DataContext for the button Something like

public class ButtonViewModel{

private RelayCommand _CloseCommand;

public ICommand CloseCommand
        {
            get { return _CloseCommand?? (_CloseCommand= new RelayCommand(p => Close())); }
        }

void Close(){

//Here u cn write the  logic which close the window from this view model or  raise an event which handled by your button container

}
}


    public class RelayCommand : ICommand
    {
        #region Fields

        private readonly Action<object> _execute;
        private 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 // Constructors

        #region ICommand Members [DebuggerStepThrough]

        public bool CanExecute(object parameter)
        {
            return _canExecute == null || _canExecute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        public void Execute(object parameter)
        {
            _execute(parameter);
        }

        #endregion // ICommand Members }
    }

in xaml

<Button x:Name="CloseButton" Command="{Binding Close}"/>

Ensure that the DataContext is availble for the button

Expose dependency property of type ICommand from class MessageBoxModule :

public ICommand CloseCommand
{
   get { return (ICommand)GetValue(CloseCommandProperty); }
   set { SetValue(CloseCommandProperty, value); }
}

public static readonly DependencyProperty CloseCommandProperty =
   DependencyProperty.Register("CloseCommand", typeof(ICommand), 
                                typeof(MessageBoxModule));

Use TemplateBinding to bind to Command like this:

<Button x:Name="CloseButton" Command="{TemplateBinding CloseCommand}"/>

Since command is exposed, you can bind to it from outside like this:

<local:MessageBoxModule CloseCommand="{Binding ViewModelCommand}"/>

Assuming you already have View model in place and it already contains ICommand to which you want to bind close button.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM