简体   繁体   English

具有可冻结StaticCource的DataGrid CellStyle设置器

[英]DataGrid CellStyle Setters with Freezable StaticRecource

I wanted to set the command of a button in a WPF datagrid with a setter. 我想使用设置器在WPF数据网格中设置按钮的命令。 But it seems that the DP property CommandProperty gets ovewritten with its default value null after I returned a copy in CreateInstanceCore() , so the original command gets lost. 但是,当我在CreateInstanceCore()返回副本后,似乎DP属性CommandProperty的默认值null被覆盖,因此原始命令丢失了。

If I bind the StaticResource directly it works without problems. 如果我直接绑定StaticResource ,它将正常工作。 Is there a way to stop that behavior or another solution? 有没有办法阻止这种行为或其他解决方案?

public class ResourceCommand : Freezable, ICommand {

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

    // Using a DependencyProperty as the backing store for Command.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof(ICommand), typeof(ResourceCommand), new UIPropertyMetadata(null, CommandPropertyChangedCallback));


    static void CommandPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        ResourceCommand resourceCommand = (ResourceCommand)d;
        int h = resourceCommand.GetHashCode();
        if (e.OldValue != null)
            ((ICommand)e.OldValue).CanExecuteChanged -= resourceCommand.OnCanExecuteChanged;
        if (e.NewValue != null)
            ((ICommand)e.NewValue).CanExecuteChanged += resourceCommand.OnCanExecuteChanged;
    }

    #region ICommand Member

    public bool CanExecute(object parameter) {
        if (Command == null)
            return false;
        return Command.CanExecute(parameter);
    }

    public event EventHandler CanExecuteChanged;

    void OnCanExecuteChanged(object sender, EventArgs e) {
        if (CanExecuteChanged != null)
            CanExecuteChanged(sender, e);
    }

    public void Execute(object parameter) {
        Command.Execute(parameter);
    }

    #endregion

    protected override Freezable CreateInstanceCore() {
        ResourceCommand ResourceCommand = new ResourceCommand();
        ResourceCommand.Command = Command;
        return ResourceCommand;
    }
}

xaml: xaml:

<Window.Resources>
    <local:ResourceCommand x:Key="FirstCommand"  Command="{Binding FirstCommand}" />
    <local:ResourceCommand x:Key="SecondCommand"  Command="{Binding SecondCommand}" />
</Window.Resources>
<Grid>
    <DataGrid ItemsSource="{Binding Collection}">
        <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button Content="Click me">
                            <Button.Style>
                                <Style TargetType="Button">
                                    <Setter Property="Command" Value="{StaticResource FirstCommand}" />
                                </Style>
                            </Button.Style></Button>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

It works if you define your resource commands like this: 如果您这样定义资源命令,它将起作用:

<local:ResourceCommand x:Key="FirstCommand" Command="{Binding FirstCommand}" x:Shared="False"/>

Using this technique you can even throw not-implemented in CreateInstanceCore and so you'll just be using Freezable to enable data binding. 使用这种技术,您甚至可以在CreateInstanceCore不使用它,因此您将仅使用Freezable启用数据绑定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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