gpt4 book ai didi

c# - 项目命令无法编辑列表中的其他项目

转载 作者:太空宇宙 更新时间:2023-11-03 12:06:15 25 4
gpt4 key购买 nike

我有一个侧边栏(在 C# WPF 程序中)应该显示 4 个“不同”按钮(它们实际上是 2 种不同的样式,它们都具有另一种事件状态样式)。侧边栏由一个 ItemsControl 组成。我现在设法创建了一个列表,其中根据枚举值使用了正确的样式(如下所示)。这里有一个小问题:我可以这样做吗,或者我应该重写它,如果是这样,如何构建这样的东西?关键字或我必须看的东西对我来说已经足够了。

我现在真正的问题是:我已经为每个按钮绑定(bind)了一个命令,一开始并不复杂。该命令现在将其自身状态设置为 NormalActive 以用于测试目的。此列表中的第一项应从 LiveActive 设置为 Live(以便您始终看到您所知道的当前所选项目)。问题来了:按钮可以设置自己的状态,所以当我点击按钮 3 时,按钮 3 的状态从 Normal 设置为 NormalActive。但是没有发生的是第一个按钮从 LiveActive 到 Active 的变化。即使我在更改前后将当前状态输出到控制台,它也会为两者返回 LiveActive。如果由于某种原因我不在 UI 线程中,我也尝试将整个事情调用到调度程序中,但它没有用。所以按钮可以设置自己的状态,但不能设置另一个按钮的状态。但我没有收到错误消息或任何信息。属性的 setter 方法也会被调用,只是不会改变它。可能是什么原因?

插件列表控件:

<Grid DataContext="{x:Static local:PluginListDesignModel.Instance}">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:PluginListItemControl />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>

PluginListItemControl:

<UserControl.Resources>
<DataTemplate x:Key="PluginTile" DataType="{x:Type local:PluginListItemViewModel}">
<Button Style="{StaticResource PluginTile}" Content="{Binding DataContext.Name, RelativeSource={RelativeSource AncestorType=ContentControl}}" Command="{Binding DataContext.SetStateCommand, RelativeSource={RelativeSource AncestorType=ContentControl}}" />
</DataTemplate>

<DataTemplate x:Key="PluginActiveTile" DataType="{x:Type local:PluginListItemViewModel}">
<Button Style="{StaticResource PluginActiveTile}" Content="{Binding DataContext.Name, RelativeSource={RelativeSource AncestorType=ContentControl}}" Command="{Binding DataContext.SetStateCommand, RelativeSource={RelativeSource AncestorType=ContentControl}}" />
</DataTemplate>

<DataTemplate x:Key="PluginLiveTile" DataType="{x:Type local:PluginListItemViewModel}">
<Button Style="{StaticResource PluginLiveTile}" Content="{Binding DataContext.Name, RelativeSource={RelativeSource AncestorType=ContentControl}}" Command="{Binding DataContext.SetStateCommand, RelativeSource={RelativeSource AncestorType=ContentControl}}" />
</DataTemplate>

<DataTemplate x:Key="PluginActiveLiveTile" DataType="{x:Type local:PluginListItemViewModel}">
<Button Style="{StaticResource PluginActiveLiveTile}" Content="{Binding DataContext.Name, RelativeSource={RelativeSource AncestorType=ContentControl}}" Command="{Binding DataContext.SetStateCommand, RelativeSource={RelativeSource AncestorType=ContentControl}}" />
</DataTemplate>
</UserControl.Resources>
<ContentControl d:DataContext="{x:Static local:PluginListItemDesignModel.Instance}">

<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate" Value="{StaticResource PluginTile}" />
<Style.Triggers>
<DataTrigger Binding="{Binding State}" Value="0">
<Setter Property="ContentTemplate" Value="{StaticResource PluginTile}" />
</DataTrigger>
<DataTrigger Binding="{Binding State}" Value="1">
<Setter Property="ContentTemplate" Value="{StaticResource PluginActiveTile}" />
</DataTrigger>
<DataTrigger Binding="{Binding State}" Value="2">
<Setter Property="ContentTemplate" Value="{StaticResource PluginLiveTile}" />
</DataTrigger>
<DataTrigger Binding="{Binding State}" Value="3">
<Setter Property="ContentTemplate" Value="{StaticResource PluginActiveLiveTile}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>

</ContentControl>

PluginListItemViewModel:(每个列表项的 ViewModel)

public class PluginListItemViewModel : BaseViewModel
{
public string Name { get; set; }
public PluginTileStates State { get; set; }
public ICommand SetStateCommand { get; set; }

#region Constructor

/// <summary>
/// Default constructor
/// </summary>
public PluginListItemViewModel()
{
SetStateCommand = new RelayCommand(() => SetState());
}

#endregion

private void SetState()
{
PluginListDesignModel.Instance.Items[0].State = PluginTileStates.Live;
State = PluginTileStates.NormalActive;
}
}

重现步骤:

  1. 创建一个新的 WPF 项目,.NET Framework 4.6.1 (Visual Studio 2017)。
  2. 用以下内容替换 MainWindow 中的网格:

<Grid DataContext="{x:Static local:ListViewModel.Instance}">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:ListItemControl />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
  1. 添加一个名为 ListItemControl 的新用户控件并将网格替换为:

<UserControl.Resources>
<Style x:Key="Tile" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red" />
</Style>

<Style x:Key="ActiveTile" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Green" />
</Style>

<DataTemplate x:Key="PluginTile" DataType="{x:Type local:ListItemViewModel}">
<Button Width="100" Height="60" Style="{StaticResource Tile}" Command="{Binding DataContext.SetStateCommand, RelativeSource={RelativeSource AncestorType=ContentControl}}" />
</DataTemplate>

<DataTemplate x:Key="PluginActiveTile" DataType="{x:Type local:ListItemViewModel}">
<Button Width="100" Height="60" Style="{StaticResource ActiveTile}" Command="{Binding DataContext.SetStateCommand, RelativeSource={RelativeSource AncestorType=ContentControl}}" />
</DataTemplate>
</UserControl.Resources>
<ContentControl>
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate" Value="{StaticResource PluginTile}" />
<Style.Triggers>
<DataTrigger Binding="{Binding State}" Value="0">
<Setter Property="ContentTemplate" Value="{StaticResource PluginTile}" />
</DataTrigger>
<DataTrigger Binding="{Binding State}" Value="1">
<Setter Property="ContentTemplate" Value="{StaticResource PluginActiveTile}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
  1. 添加一个名为 BaseViewModel 的新类并将类替换为:

public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };

public void OnPropertyChanged(string name)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
  1. 添加名为 ListItemViewModel 的新类并将类替换为:

public enum TileStates
{
Normal = 0,
Active = 1
}

public class ListItemViewModel : BaseViewModel
{
public TileStates State { get; set; }

public ICommand SetStateCommand { get; set; }

public ListItemViewModel()
{
SetStateCommand = new RelayCommand(() =>
{
ListViewModel.Instance.Items[0].State = TileStates.Normal;
State = TileStates.Active;
});
}
}
  1. 添加名为 ListViewModel 的新类并将类替换为:

public class ListViewModel : BaseViewModel
{
public static ListViewModel Instance => new ListViewModel();

public List<ListItemViewModel> Items { get; set; } = new List<ListItemViewModel>
{
new ListItemViewModel
{
State = TileStates.Active
},
new ListItemViewModel
{
State = TileStates.Normal
}
};
}
  1. 添加名为 RelayCommand 的新类并将类替换为:

public class RelayCommand : ICommand
{
private Action mAction;

public event EventHandler CanExecuteChanged = (sender, e) => { };

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

public bool CanExecute(object parameter)
{
return true;
}

public void Execute(object parameter)
{
mAction();
}
}
  1. 安装 NuGet 包:“Fody v4.0.2”和“PropertyChanged.Fody v2.6.0”(您可能需要在安装后重新启动 Visual Studio

如果你现在按下底部的按钮,它应该变成绿色,而顶部的按钮应该变成红色。

最佳答案

ListViewModel.Instance 每次被调用时都会返回一个 ListViewModel 类的新实例。它应该返回相同的实例:

public static ListViewModel Instance { get; } = new ListViewModel();

关于c# - 项目命令无法编辑列表中的其他项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54824560/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com