EDIT2: 我正在处理一些项目,其中我的ComboBox包含一个可编辑元素列表。选择其中一个元素后,这些元素可以编辑。我想要的是当我取消选择时,所选元素的编辑属性会被记住,并且ComboBox下拉列表会使用新元素进行更新。说明。以下是此示例的示例:
现在切换后会记住更改,但下拉列表仍包含旧名称,并且不会自动更新:
这是代码。
MainWindow.xaml
<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>
MainViewModel.cs
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));
OnPropertyChanged(nameof(Name));
OnPropertyChanged(nameof(Price));
//OnPropertyChanged(nameof(Things));
}
}
public string Name
{
get
{
if (SelectedThing != null)
{
return SelectedThing.Name;
}
return null;
}
set
{
SelectedThing.Name = value;
OnPropertyChanged(nameof(Name));
}
}
public string Price
{
get
{
if (SelectedThing != null)
{
return SelectedThing.Price;
}
return null;
}
set
{
SelectedThing.Price = value;
OnPropertyChanged(nameof(Price));
}
}
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(), null);
}
return cloneCommand;
}
}
public ICommand DeleteCommand
{
get
{
if(deleteCommand==null)
{
deleteCommand = new CommandBase(i => DeleteItem(), 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;
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);
}
}
}
Thing.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MVVMEditComboBoxItemsSample.MockModel
{
class Thing
{
public string Name { get; set; }
public string Price { get; set; }
public override string ToString()
{
return Name;
}
}
}
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;
}
}
}
我希望像ViewModelBase和CommandBase这样的其他内容足够自我描述:)。
为什么我的下拉列表没有使用当前的名称更新的任何想法?
编辑: 好的,我在github上传了简化版:
github.com/piotr-napadlek/MVVMEditComboBoxItemsSample
仍然无法正常工作的是,更改“名称”文本框的值时,ComboBox下拉菜单的项目不会发生变化。另外,如果本例中的一般方法是正确的,请告诉我。欢呼声。
答案 0 :(得分:0)
如果您查看本文中的示例项目,它将为您提供有关MVVM应用程序的良好体系结构的想法。它使用的是Silverlight,它只是WPF的精简版本:
http://www.codeproject.com/Articles/854816/MVVM-Silverlight-Application-with-Entity-Framework
答案 1 :(得分:0)
视图模型:
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);
}
}
}
的MainView:
<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>