Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF MVVM RelayCommand在每个DataGrid行上有多个按钮,仅为选定行设置启用/禁用按钮状态_C#_Wpf_Mvvm_Datagrid_Relaycommand - Fatal编程技术网

C# WPF MVVM RelayCommand在每个DataGrid行上有多个按钮,仅为选定行设置启用/禁用按钮状态

C# WPF MVVM RelayCommand在每个DataGrid行上有多个按钮,仅为选定行设置启用/禁用按钮状态,c#,wpf,mvvm,datagrid,relaycommand,C#,Wpf,Mvvm,Datagrid,Relaycommand,WPF MVVM 中继命令 using System; using System.Windows.Input; namespace Multthreading { public class RelayCommand : ICommand { Action _TargetExecuteMethod; Func<bool> _TargetCanExecuteMethod; public RelayCommand(Action executeMethod)

WPF

MVVM

中继命令

using System;
using System.Windows.Input;

namespace Multthreading
{
public class RelayCommand : ICommand
{
    Action _TargetExecuteMethod;
    Func<bool> _TargetCanExecuteMethod;

    public RelayCommand(Action executeMethod)
    {
        _TargetExecuteMethod = executeMethod;
    }

    public RelayCommand(Action executeMethod, Func<bool> canExecuteMethod)
    {
        _TargetExecuteMethod = executeMethod;
        _TargetCanExecuteMethod = canExecuteMethod;
    }

    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged(this, EventArgs.Empty);
    }
    #region ICommand Members

    bool ICommand.CanExecute(object parameter)
    {
        if (_TargetCanExecuteMethod != null)
        {
            return _TargetCanExecuteMethod();
        }
        if (_TargetExecuteMethod != null)
        {
            return true;
        }
        return false;
    }

    // Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
    // Prism commands solve this in their implementation
    public event EventHandler CanExecuteChanged = delegate { };

    void ICommand.Execute(object parameter)
    {
        if (_TargetExecuteMethod != null)
        {
            _TargetExecuteMethod();
        }
    }
    #endregion
}

public class RelayCommand<T> : ICommand
{
    Action<T> _TargetExecuteMethod;
    Func<T, bool> _TargetCanExecuteMethod;

    public RelayCommand(Action<T> executeMethod)
    {
        _TargetExecuteMethod = executeMethod;
    }

    public RelayCommand(Action<T> executeMethod, Func<T,bool> canExecuteMethod)
    {
        _TargetExecuteMethod = executeMethod;
        _TargetCanExecuteMethod = canExecuteMethod;
    }

    public void RaiseCanExecuteChanged() 
    {
         CanExecuteChanged(this, EventArgs.Empty); 
    }
    #region ICommand Members

    bool ICommand.CanExecute(object parameter)
    {
        if (_TargetCanExecuteMethod != null)
        {
            T tparm = (T)parameter;
            return _TargetCanExecuteMethod(tparm);
        }
        if (_TargetExecuteMethod != null)
        {
            return true;
        }
        return false;
    }

    // Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
    // Prism commands solve this in their implementation
    public event EventHandler CanExecuteChanged = delegate { };

    void ICommand.Execute(object parameter)
    {
        if (_TargetExecuteMethod != null)
        {
            _TargetExecuteMethod((T)parameter);
        }
    }
    #endregion
    }
}
数据网格,每行有多个按钮。

目标:单击“开始”按钮时,仅启用和禁用选定行的某些按钮

当前行为:当我单击“开始”按钮时,所有行的按钮都会以相同的方式启用和禁用

在这幅图中,您可以看到我单击了Start按钮,并启动了命令,正确设置了其他按钮的启用/禁用状态,但它将其应用于所有行

我一直在努力让它只适用于选定的项目。 我目前正在尝试将一个参数传递给RelayCommand,如果有人能告诉我如何做,也许它会起作用

XAML

<DataGrid x:Name="dataGridThreadView" Grid.Row="1" Grid.Column="0" AutoGenerateColumns="False" 
                  IsReadOnly="True" CanUserResizeRows="False" CanUserReorderColumns="True" Margin="4"  
                  CanUserAddRows="False" CanUserDeleteRows="False" CanUserSortColumns="True" 
                  EnableRowVirtualization="True" ItemsSource="{Binding Threads}"
                  SelectedItem="{Binding Path=SelectedThread, Mode=TwoWay}">

            <DataGrid.Columns>
                <DataGridTextColumn Header="Name"
                        Binding="{Binding Thread.Name}"/>
                <DataGridTemplateColumn Header="Actions">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal" Margin="2">
                                <Button Name="buttonStartThread" Content="Start" Command="{Binding ElementName=dataGridThreadView,  Path=DataContext.StartCommand}" CommandParameter="{Binding SelectedThread}"/>
                                <Button Name="buttonSuspendThread" Content="Suspend" Command="{Binding ElementName=dataGridThreadView,  Path=DataContext.SuspendCommand}"/>
                                <Button Name="buttonResumeThread" Content="Resume" Command="{Binding ElementName=dataGridThreadView,  Path=DataContext.ResumeCommand}"/>
                                <Button Name="buttonInterruptThread" Content="Interrupt" Command="{Binding ElementName=dataGridThreadView,  Path=DataContext.InterruptCommand}"/>
                                <Button Name="buttonAbortThread" Content="Abort" Command="{Binding ElementName=dataGridThreadView,  Path=DataContext.AbortCommand}"/>
                            </StackPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

视图模型

 public class ThreadViewModel : PropertyChangedBase
{
    public ThreadModel SelectedThread { get; set; }
    public ObservableCollection<ThreadModel> Threads { get; set; }
    private bool _disableStartButton = false;
    private bool _disableSuspendButton = false;
    private bool _disableResumeButton = false;
    private bool _disableInterruptButton = false;
    private bool _disableAbortButton = false;

    public RelayCommand StartCommand { get; private set; } // should only be set once in vm during construction

    public ThreadViewModel()
    {
        _disableStartButton = false;
        _disableSuspendButton = true;
        _disableResumeButton = true;
        _disableInterruptButton = true;
        _disableAbortButton = true;
        Threads = new ObservableCollection<ThreadModel>();

        StartCommand = new RelayCommand(OnStart, CanStart);
    }

    private void OnStart(object template)
    {
        this._disableStartButton = true;
        StartCommand.RaiseCanExecuteChanged();
        _disableSuspendButton = false;
        SuspendCommand.RaiseCanExecuteChanged();
        _disableInterruptButton = false;
        InterruptCommand.RaiseCanExecuteChanged();
        _disableAbortButton = false;
        AbortCommand.RaiseCanExecuteChanged();
    }

    private bool CanStart()
    {
        return !this._disableStartButton;
    }
}
公共类ThreadViewModel:PropertyChangedBase
{
public ThreadModel SelectedThread{get;set;}
公共ObservableCollection线程{get;set;}
private bool_disableStartButton=false;
private bool_disableSuspendButton=false;
private bool\u disableResumeButton=false;
private bool _disableInterruptButton=false;
私有布尔_disableAbortButton=false;
public RelayCommand StartCommand{get;private set;}//在构建期间只能在vm中设置一次
公共线程视图模型()
{
_disableStartButton=false;
_disableSuspendButton=true;
_disableResumeButton=true;
_disableInterruptButton=true;
_disableAbortButton=true;
线程=新的ObservableCollection();
StartCommand=新的中继命令(OnStart,CanStart);
}
私有void OnStart(对象模板)
{
这是。_disableStartButton=true;
StartCommand.RaiseCanExecuteChanged();
_disableSuspendButton=false;
SuspendCommand.RaiseCanExecuteChanged();
_disableInterruptButton=false;
InterruptCommand.RaiseCanExecuteChanged();
_disableAbortButton=false;
AbortCommand.RaiseCanExecuteChanged();
}
私人bool CanStart()
{
返回!这个。\ u禁用开始按钮;
}
}
RelayCommand类

using System;
using System.Windows.Input;

namespace Multthreading
{
public class RelayCommand : ICommand
{
    Action _TargetExecuteMethod;
    Func<bool> _TargetCanExecuteMethod;

    public RelayCommand(Action executeMethod)
    {
        _TargetExecuteMethod = executeMethod;
    }

    public RelayCommand(Action executeMethod, Func<bool> canExecuteMethod)
    {
        _TargetExecuteMethod = executeMethod;
        _TargetCanExecuteMethod = canExecuteMethod;
    }

    public void RaiseCanExecuteChanged()
    {
        CanExecuteChanged(this, EventArgs.Empty);
    }
    #region ICommand Members

    bool ICommand.CanExecute(object parameter)
    {
        if (_TargetCanExecuteMethod != null)
        {
            return _TargetCanExecuteMethod();
        }
        if (_TargetExecuteMethod != null)
        {
            return true;
        }
        return false;
    }

    // Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
    // Prism commands solve this in their implementation
    public event EventHandler CanExecuteChanged = delegate { };

    void ICommand.Execute(object parameter)
    {
        if (_TargetExecuteMethod != null)
        {
            _TargetExecuteMethod();
        }
    }
    #endregion
}

public class RelayCommand<T> : ICommand
{
    Action<T> _TargetExecuteMethod;
    Func<T, bool> _TargetCanExecuteMethod;

    public RelayCommand(Action<T> executeMethod)
    {
        _TargetExecuteMethod = executeMethod;
    }

    public RelayCommand(Action<T> executeMethod, Func<T,bool> canExecuteMethod)
    {
        _TargetExecuteMethod = executeMethod;
        _TargetCanExecuteMethod = canExecuteMethod;
    }

    public void RaiseCanExecuteChanged() 
    {
         CanExecuteChanged(this, EventArgs.Empty); 
    }
    #region ICommand Members

    bool ICommand.CanExecute(object parameter)
    {
        if (_TargetCanExecuteMethod != null)
        {
            T tparm = (T)parameter;
            return _TargetCanExecuteMethod(tparm);
        }
        if (_TargetExecuteMethod != null)
        {
            return true;
        }
        return false;
    }

    // Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
    // Prism commands solve this in their implementation
    public event EventHandler CanExecuteChanged = delegate { };

    void ICommand.Execute(object parameter)
    {
        if (_TargetExecuteMethod != null)
        {
            _TargetExecuteMethod((T)parameter);
        }
    }
    #endregion
    }
}
使用系统;
使用System.Windows.Input;
名称空间多线程
{
公共类中继命令:ICommand
{
行动-目标执行方法;
Funcu TargetCanExecuteMethod;
公共中继命令(操作执行方法)
{
_TargetExecuteMethod=执行方法;
}
公共中继命令(操作执行方法、函数执行方法)
{
_TargetExecuteMethod=执行方法;
_TargetCanExecuteMethod=canExecuteMethod;
}
public void raisecancecutechanged()
{
CanExecuteChanged(此为EventArgs.Empty);
}
#区域ICommand成员
bool ICommand.CanExecute(对象参数)
{
如果(_TargetCanExecuteMethod!=null)
{
返回_TargetCanExecuteMethod();
}
如果(_TargetExecuteMethod!=null)
{
返回true;
}
返回false;
}
//当心-若命令实例生存期长于连接到命令的UI对象的生存期,则应使用弱引用
//Prism命令在其实现中解决了这一问题
公共事件事件处理程序CanExecuteChanged=委托{};
void ICommand.Execute(对象参数)
{
如果(_TargetExecuteMethod!=null)
{
_TargetExecuteMethod();
}
}
#端区
}
公共类中继命令:ICommand
{
行动-目标执行方法;
Funcu TargetCanExecuteMethod;
公共中继命令(操作执行方法)
{
_TargetExecuteMethod=执行方法;
}
公共中继命令(操作执行方法、函数执行方法)
{
_TargetExecuteMethod=执行方法;
_TargetCanExecuteMethod=canExecuteMethod;
}
public void raisecancecutechanged()
{
CanExecuteChanged(此为EventArgs.Empty);
}
#区域ICommand成员
bool ICommand.CanExecute(对象参数)
{
如果(_TargetCanExecuteMethod!=null)
{
T tparm=(T)参数;
返回_TargetCanExecuteMethod(tparm);
}
如果(_TargetExecuteMethod!=null)
{
返回true;
}
返回false;
}
//当心-若命令实例生存期长于连接到命令的UI对象的生存期,则应使用弱引用
//Prism命令在其实现中解决了这一问题
公共事件事件处理程序CanExecuteChanged=委托{};
void ICommand.Execute(对象参数)
{
如果(_TargetExecuteMethod!=null)
{
_TargetExecuteMethod((T)参数);
}
}
#端区
}
}

一种可能的解决方案是使用
绑定。
每行绑定到不同的项,因此每个项都可以将其各自的属性绑定到按钮的属性

您必须在对象的模型中提供额外的属性。您可以将简单的
booleans
绑定到按钮的
IsEnabled
属性。将默认值设置为false。
这样,您就可以编辑所选项目的属性,并自动更改相应按钮的属性。

一种可能的解决方案是使用
绑定。