C# 在一个表单中编辑列表中的项目-MVVM方法
编辑2: 我正在做一个项目,其中我的组合框包含一个可编辑元素列表。选择其中一个元素后,这些元素可编辑。我想要的是,当我取消选择所选元素时,它的编辑属性会被记住,并且组合框下拉列表会用新元素的描述更新。下面是这个示例的样子: 现在,切换后会记住更改,但下拉列表仍然包含旧名称,并且不会自动更新: 这是密码 main window.xamlC# 在一个表单中编辑列表中的项目-MVVM方法,c#,.net,wpf,mvvm,C#,.net,Wpf,Mvvm,编辑2: 我正在做一个项目,其中我的组合框包含一个可编辑元素列表。选择其中一个元素后,这些元素可编辑。我想要的是,当我取消选择所选元素时,它的编辑属性会被记住,并且组合框下拉列表会用新元素的描述更新。下面是这个示例的样子: 现在,切换后会记住更改,但下拉列表仍然包含旧名称,并且不会自动更新: 这是密码 main window.xaml <Window x:Class="MVVMEditComboBoxItemsSample.MainWindow" xmlns="http
<Window x:Class="MVVMEditComboBoxItemsSample.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:MVVMEditComboBoxItemsSample"
mc:Ignorable="d"
Title="MVVM ComboBox edit sample" Height="372.52" Width="415.214">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50*"></RowDefinition>
<RowDefinition Height="81*"/>
<RowDefinition Height="26*"/>
<RowDefinition Height="45*"/>
<RowDefinition Height="26*"/>
<RowDefinition Height="44*"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Margin="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" ItemsSource="{Binding Path=Things}" SelectedItem="{Binding Path=SelectedThing, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"></ComboBox>
<StackPanel Grid.Row="1" Margin="10">
<Button Command="{Binding Path=AddCommand}">Add Item</Button>
<Button Command="{Binding Path=CloneCommand}">Clone Item</Button>
<Button Command="{Binding Path=DeleteCommand}">Delete Item</Button>
</StackPanel>
<Label Grid.Row="2" Margin="0" >Name</Label>
<TextBox Grid.Row="3" HorizontalAlignment="Stretch" Margin="10" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Text="{Binding Path=Name}"/>
<Label Grid.Row="4" Margin="0" >Price</Label>
<TextBox Grid.Row="5" HorizontalAlignment="Stretch" Margin="10" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Text="{Binding Path=Price}"/>
</Grid>
</Window>
ThingDataManager
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MVVMEditComboBoxItemsSample.MockModel
{
class ThingDataManager
{
private static ThingDataManager _instance;
public static ThingDataManager Instance
{
get
{
if (_instance==null)
{
_instance = new ThingDataManager();
}
return _instance;
}
}
private ThingDataManager()
{
}
public List<Thing> GetThings()
{
List<Thing> things = new List<Thing>();
things.Add(new Thing { Name = "Book", Price = "12$" });
things.Add(new Thing { Name = "Hammer", Price = "2$" });
things.Add(new Thing { Name = "Fridge", Price = "1200$" });
return things;
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
命名空间MVVMEditComboxItemsSample.MockModel
{
类ThingDataManager
{
私有静态ThingDataManager_实例;
公共静态ThingDataManager实例
{
得到
{
if(_instance==null)
{
_instance=newthingdatamanager();
}
返回_实例;
}
}
私有ThingDataManager()
{
}
公共列表GetThings()
{
列出事物=新列表();
添加(新事物{Name=“Book”,Price=“12$”});
添加(新事物{Name=“Hammer”,Price=“2$”});
添加(新事物{Name=“冰箱”,Price=“1200$”});
归还物品;
}
}
}
我希望像ViewModelBase和CommandBase这样的其余部分足够自我描述:)
你知道为什么我的下拉列表没有用当前的事物名称更新吗
编辑:
好的,我在github上上传了简化版:
github.com/piotr-napadlek/mvvmeditcomboxItemsSample
仍然不起作用的是,当更改Name textbox的值时,ComboBox下拉列表的项不会更改。另外,请让我知道这个例子中的一般方法是否正确。干杯。如果您查看本文中的示例项目,它将为您提供MVVM应用程序的良好体系结构的概念和想法。它使用的是Silverlight,它只是WPF的精简版本:
好吧,看来我把事情弄得太复杂了。将对象类的属性映射到ViewModel中的另一个属性是多余的。实际上,将WPF窗口上的文本框直接映射到SelectedThing.Name和SelectedThing.Price,并调用仅在SelectedThing上更改的属性,就足以解决我的问题。以下是工作版本: 视图模型:
using MVVMEditComboBoxItemsSample.MockModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace MVVMEditComboBoxItemsSample
{
class MainViewModel : ViewModelBase
{
private ObservableCollection<Thing> things;
private Thing selectedThing;
private ICommand addCommand;
private ICommand cloneCommand;
private ICommand deleteCommand;
public MainViewModel()
{
Things = new ObservableCollection<Thing>(ThingDataManager.Instance.GetThings());
SelectedThing = Things.FirstOrDefault();
}
public ObservableCollection<Thing> Things
{
get
{
return things;
}
set
{
things = value;
OnPropertyChanged(nameof(Things));
}
}
public Thing SelectedThing
{
get
{
return selectedThing;
}
set
{
selectedThing = value;
OnPropertyChanged(nameof(SelectedThing));
}
}
public ICommand AddCommand
{
get
{
if(addCommand==null)
{
addCommand = new CommandBase(i => AddItem(), null);
}
return addCommand;
}
}
public ICommand CloneCommand
{
get
{
if(cloneCommand==null)
{
cloneCommand = new CommandBase(i => CloneItem(), i => SelectedThing!=null);
}
return cloneCommand;
}
}
public ICommand DeleteCommand
{
get
{
if(deleteCommand==null)
{
deleteCommand = new CommandBase(i => DeleteItem(), i => SelectedThing!=null);
}
return deleteCommand;
}
}
public void AddItem()
{
Thing newThing = new Thing();
Things.Add(newThing);
SelectedThing = newThing;
}
public void CloneItem()
{
Thing clonedThing = new Thing();
clonedThing.Name = SelectedThing.Name + " - copy";
clonedThing.Price = SelectedThing.Price;
Things.Add(clonedThing);
SelectedThing = clonedThing;
}
public void DeleteItem()
{
Thing tempThing = new Thing();
tempThing = SelectedThing;
if (Things.IndexOf(SelectedThing) != 0)
{
SelectedThing = Things.FirstOrDefault();
}
else if (Things.Count==1)
{
SelectedThing = null;
}
else
{
SelectedThing = Things[1];
}
Things.Remove(tempThing);
}
}
使用mvvmeditcomboxItemsSample.MockModel;
使用制度;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows.Input;
命名空间MVVMEditComboxItemsSample
{
类MainViewModel:ViewModelBase
{
私人可观察的收集物品;
私事;
私有ICommand addCommand;
私人ICommand cloneCommand;
私有ICommand deleteCommand;
公共主视图模型()
{
Things=newobserveCollection(ThingDataManager.Instance.GetThings());
SelectedThing=Things.FirstOrDefault();
}
公众可观察到的收集物品
{
得到
{
归还物品;
}
设置
{
事物=价值;
财产变更(事物名称);
}
}
公共物品选择
{
得到
{
返回所选内容;
}
设置
{
选择的内容=值;
关于已更改的属性(名称(所选内容));
}
}
公共ICommand AddCommand
{
得到
{
if(addCommand==null)
{
addCommand=newcommandbase(i=>AddItem(),null);
}
返回addCommand;
}
}
公共ICommand CloneCommand
{
得到
{
if(cloneCommand==null)
{
cloneCommand=newcommandbase(i=>CloneItem(),i=>SelectedThing!=null);
}
返回克隆命令;
}
}
公共ICommand delete命令
{
得到
{
如果(deleteCommand==null)
{
deleteCommand=new CommandBase(i=>DeleteItem(),i=>SelectedThing!=null);
}
返回删除命令;
}
}
公共无效附加项()
{
新事物;
添加(newThing);
所选内容=新内容;
}
公共空克隆项()
{
事物克隆事物=新事物();
clonedThing.Name=SelectedThing.Name+“-copy”;
clonedThing.Price=选择的thing.Price;
事物。添加(克隆事物);
SelectedThing=clonedThing;
}
公共无效删除项()
{
事物诱惑=新事物();
诱惑=选择的事物;
if(Things.IndexOf(SelectedThing)!=0)
{
SelectedThing=Things.FirstOrDefault();
}
else if(Things.Count==1)
{
SelectedThing=null;
}
其他的
{
SelectedThing=事物[1];
}
事物。移除(诱惑);
}
}
}
主视图:
<Window x:Class="MVVMEditComboBoxItemsSample.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:MVVMEditComboBoxItemsSample"
mc:Ignorable="d"
Title="MVVM ComboBox edit sample" Height="372.52" Width="415.214">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50*"></RowDefinition>
<RowDefinition Height="81*"/>
<RowDefinition Height="26*"/>
<RowDefinition Height="45*"/>
<RowDefinition Height="26*"/>
<RowDefinition Height="44*"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Margin="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" ItemsSource="{Binding Path=Things}" SelectedItem="{Binding Path=SelectedThing, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" DisplayMemberPath="Name"></ComboBox>
<StackPanel Grid.Row="1" Margin="10">
<Button Command="{Binding Path=AddCommand}">Add Item</Button>
<Button Command="{Binding Path=CloneCommand}">Clone Item</Button>
<Button Command="{Binding Path=DeleteCommand}">Delete Item</Button>
</StackPanel>
<Label Grid.Row="2" Margin="0" >Name</Label>
<TextBox Grid.Row="3" HorizontalAlignment="Stretch" Margin="10" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Text="{Binding Path=SelectedThing.Name, UpdateSourceTrigger=PropertyChanged}"/>
<Label Grid.Row="4" Margin="0" >Price</Label>
<TextBox Grid.Row="5" HorizontalAlignment="Stretch" Margin="10" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Text="{Binding Path=SelectedThing.Price}"/>
</Grid>
添加项
克隆项目
删除项目
名称
价格
using MVVMEditComboBoxItemsSample.MockModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace MVVMEditComboBoxItemsSample
{
class MainViewModel : ViewModelBase
{
private ObservableCollection<Thing> things;
private Thing selectedThing;
private ICommand addCommand;
private ICommand cloneCommand;
private ICommand deleteCommand;
public MainViewModel()
{
Things = new ObservableCollection<Thing>(ThingDataManager.Instance.GetThings());
SelectedThing = Things.FirstOrDefault();
}
public ObservableCollection<Thing> Things
{
get
{
return things;
}
set
{
things = value;
OnPropertyChanged(nameof(Things));
}
}
public Thing SelectedThing
{
get
{
return selectedThing;
}
set
{
selectedThing = value;
OnPropertyChanged(nameof(SelectedThing));
}
}
public ICommand AddCommand
{
get
{
if(addCommand==null)
{
addCommand = new CommandBase(i => AddItem(), null);
}
return addCommand;
}
}
public ICommand CloneCommand
{
get
{
if(cloneCommand==null)
{
cloneCommand = new CommandBase(i => CloneItem(), i => SelectedThing!=null);
}
return cloneCommand;
}
}
public ICommand DeleteCommand
{
get
{
if(deleteCommand==null)
{
deleteCommand = new CommandBase(i => DeleteItem(), i => SelectedThing!=null);
}
return deleteCommand;
}
}
public void AddItem()
{
Thing newThing = new Thing();
Things.Add(newThing);
SelectedThing = newThing;
}
public void CloneItem()
{
Thing clonedThing = new Thing();
clonedThing.Name = SelectedThing.Name + " - copy";
clonedThing.Price = SelectedThing.Price;
Things.Add(clonedThing);
SelectedThing = clonedThing;
}
public void DeleteItem()
{
Thing tempThing = new Thing();
tempThing = SelectedThing;
if (Things.IndexOf(SelectedThing) != 0)
{
SelectedThing = Things.FirstOrDefault();
}
else if (Things.Count==1)
{
SelectedThing = null;
}
else
{
SelectedThing = Things[1];
}
Things.Remove(tempThing);
}
}
<Window x:Class="MVVMEditComboBoxItemsSample.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:MVVMEditComboBoxItemsSample"
mc:Ignorable="d"
Title="MVVM ComboBox edit sample" Height="372.52" Width="415.214">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50*"></RowDefinition>
<RowDefinition Height="81*"/>
<RowDefinition Height="26*"/>
<RowDefinition Height="45*"/>
<RowDefinition Height="26*"/>
<RowDefinition Height="44*"/>
</Grid.RowDefinitions>
<ComboBox Grid.Row="0" Margin="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" ItemsSource="{Binding Path=Things}" SelectedItem="{Binding Path=SelectedThing, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" DisplayMemberPath="Name"></ComboBox>
<StackPanel Grid.Row="1" Margin="10">
<Button Command="{Binding Path=AddCommand}">Add Item</Button>
<Button Command="{Binding Path=CloneCommand}">Clone Item</Button>
<Button Command="{Binding Path=DeleteCommand}">Delete Item</Button>
</StackPanel>
<Label Grid.Row="2" Margin="0" >Name</Label>
<TextBox Grid.Row="3" HorizontalAlignment="Stretch" Margin="10" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Text="{Binding Path=SelectedThing.Name, UpdateSourceTrigger=PropertyChanged}"/>
<Label Grid.Row="4" Margin="0" >Price</Label>
<TextBox Grid.Row="5" HorizontalAlignment="Stretch" Margin="10" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Text="{Binding Path=SelectedThing.Price}"/>
</Grid>