我有一个非常复杂的ListViews结构。在此结构内部是TextBoxes,其中包含我的ViewModel中的值。当我在某些文本框中更改值时,ViewModel中的属性不会更新。 ViewModel中的“ AllTexts”属性仍然仅包含“ Hello”字符串。
基本上,我想显示用户的字符串结构,然后让用户更改此结构。他完成修改后,我要保存他的更改。 “ Hello”字符串仅用于测试。
我的ViewModel:
class MainWindowViewModel
{
public ObservableCollection<ObservableCollection<ObservableCollection<string>>> AllTexts { get; set; }
public int SelectedGroupIndex { get; set; }
public int SelectedColumnIndex { get; set; }
public ICommand AddGroup { get; private set; }
public ICommand AddColumn { get; private set; }
public MainWindowViewModel()
{
this.AllTexts = new ObservableCollection<ObservableCollection<ObservableCollection<string>>>();
this.SelectedGroupIndex = -1;
this.SelectedColumnIndex = -1;
this.AddGroup = new Command(this.AddGroupCommandHandler);
this.AddColumn = new Command(this.AddColumnCommandHandler);
}
private void AddGroupCommandHandler()
{
var tempColumn = new ObservableCollection<string>() { "Hello", "Hello", "Hello", "Hello", "Hello" };
var tempGroup = new ObservableCollection<ObservableCollection<string>>();
tempGroup.Add(tempColumn);
this.AllTexts.Add(new ObservableCollection<ObservableCollection<string>>(tempGroup));
}
private void AddColumnCommandHandler()
{
if (this.SelectedGroupIndex >= 0 && this.SelectedGroupIndex < this.AllTexts.Count)
{
var tempColumn = new ObservableCollection<string>() { "Hello", "Hello", "Hello", "Hello", "Hello" };
this.AllTexts[this.SelectedGroupIndex].Add(tempColumn);
}
}
}
我的视图:
<Window.Resources>
<ResourceDictionary>
<local:MainWindowViewModel x:Key="vm" />
</ResourceDictionary>
</Window.Resources>
<Grid Margin="10,10,10,10" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="300" />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ListView Grid.Row="0"
ItemsSource="{Binding AllTexts, Source={StaticResource vm}, Mode=TwoWay}"
Background="Red"
SelectedIndex="{Binding SelectedGroupIndex, Source={StaticResource vm}}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<ListView
Background="Yellow"
ItemsSource="{Binding Path=., Mode=TwoWay}"
SelectedIndex="{Binding SelectedColumnIndex, Source={StaticResource vm}}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<ListView
Background="Green"
ItemsSource="{Binding Path=., Mode=TwoWay}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Path=., Mode=TwoWay, NotifyOnSourceUpdated=True}"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Center"
Width="100" Height="40"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel Grid.Row="1" Orientation="Horizontal" Margin="0,20,0,0">
<Button Content="Add Group" Width="120" Height="30"
Command="{Binding AddGroup, Source={StaticResource vm}}" />
<Button Content="Add Column" Margin="20,0,0,0" Width="120" Height="30"
Command="{Binding AddColumn, Source={StaticResource vm}}" />
</StackPanel>
<StackPanel Grid.Row="2" Orientation="Horizontal" Margin="0,20,0,0">
<TextBlock Width="120" Height="30" FontSize="20"
Text="{Binding SelectedGroupIndex, Source={StaticResource vm}}" />
<TextBlock Width="120" Height="30" Margin="20,0,0,0" FontSize="20"
Text="{Binding SelectedColumnIndex, Source={StaticResource vm}}" />
</StackPanel>
</Grid>
有人可以帮我吗? 谢谢。
答案 0 :(得分:1)
您的ViewModel必须通知View有关更改,否则View保留ViewModel的原始值
在这种情况下,string
无法通知对其所做的更改。只有其封闭的可观察集合可以通知其对自身所做的更改(例如添加或删除),并且不会对其元素进行进一步监视。
因此,您需要一个可观察的字符串:
public class MyString : DependencyObject
{
public string Value
{
get { return (string)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(string), typeof(MyString), new PropertyMetadata(""));
}
要在集合中使用:
public ObservableCollection<ObservableCollection<ObservableCollection<MyString>>> AllTexts { get; set; }
我还向MyString
类添加了以下行,以便测试代码并能正常工作。
public static MyString Hello { get { return new MyString { Value = "Hello" }; } }
很明显,这是它的用法:
var tempColumn = new ObservableCollection<MyString>() { MyString.Hello, MyString.Hello, MyString.Hello, MyString.Hello, MyString.Hello };
在xaml中,还有一些不必要的东西可以消除:
对两个ItemsSource="{Binding}"
使用ListView
,对Text="{Binding Value}"
使用TextBox
。 (在任何一种情况下都不需要显式TwoWay
)