我有一个DataGrid
,其ItemsSource
绑定到ViewModel类型ObservableCollection(of MY_TYPE)
的属性。另外,在ViewModel中我还有一个名为SelectedTarget
的属性,它绑定到SelectedItem
的{{1}}(类型当然是MY_TYPE)。
现在我想要实现的是:用户可以将光标移动到另一行,只要前一行(DataGrid
)没有任何更改,否则他必须首先保存这些更改。但我不知道该怎么做。
感谢您的帮助!
更新
这是我的xaml代码和ViewModel属性,就像Sheridan所建议的那样。
xaml
SelectedTarget
ViewModel中的属性:
<DataGrid Grid.Column="1" x:Name="ItemsGrid" ItemsSource="{Binding MyItems}" SelectionMode="Single" AutoGenerateColumns="False"
CanUserResizeRows="False" CanUserSortColumns="True" IsReadOnly="True" VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Standard" EnableRowVirtualization="True"
SelectedItem="{Binding SelectedTarget, Mode=TwoWay}"
SelectionUnit="FullRow">
我已经检查过,当Public Property SelectedTarget As MY_TYPE
Get
Return _selectedTarget
End Get
Set(value As MY_TYPE)
If _selectedTarget Is Nothing OrElse (_selectedTarget.Status <> Status.Editing AndAlso _selectedTarget.Status <> Status.New) Then
_selectedTarget = value
RaisePropertyChanged("SelectedTarget")
End If
End Set
End Property
Private _selectedTarget As MY_TYPE
Status
正在编辑时,它本身不会更改SelectedTarget
。但是,这不会阻止另一行中的值进行更改。无论如何,光标会移动到另一行,但我不确定这是否意味着我的SelectedTarget
绑定无法正常工作。另一方面,如果我根本没有在SelectedItem
中设置SelectedItem
的绑定,即使我没有在第一行中保存更改,值仍会在第二行中更改。这是有道理的,因为无论如何每一行都是自然地绑定到一个项目。
答案 0 :(得分:2)
以下是如何执行此操作的示例。我知道它的丑陋,但你明白了。)
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new VM();
}
}
public class VM : INotifyPropertyChanged
{
private ObservableCollection<MyItem> mySource;
private MyItem myTarget;
public ObservableCollection<MyItem> MySource
{
get { return mySource; }
set { mySource = value; }
}
public MyItem MyTarget
{
get { return myTarget; }
set
{
if (myTarget == null)
myTarget = value;
else if (myTarget.IsSaved)
myTarget = value;
INotifyPropertyChanged("MyTarget");
}
}
public VM()
{
mySource = new ObservableCollection<MyItem>();
mySource.Add(new MyItem { Text1 = "1", Text2 = "8" });
mySource.Add(new MyItem { Text1 = "2", Text2 = "7" });
mySource.Add(new MyItem { Text1 = "3", Text2 = "6" });
mySource.Add(new MyItem { Text1 = "4", Text2 = "5" });
mySource.Add(new MyItem { Text1 = "5", Text2 = "4" });
mySource.Add(new MyItem { Text1 = "6", Text2 = "3" });
mySource.Add(new MyItem { Text1 = "7", Text2 = "2" });
mySource.Add(new MyItem { Text1 = "8", Text2 = "1" });
}
//INotifyPropertyChanged
}
public class MyItem : INotifyPropertyChanged
{
private string text1;
public string Text1
{
get { return text1; }
set
{
text1 = value;
isSaved = false;
INotifyPropertyChanged("Text1");
INotifyPropertyChanged("IsSaved");
}
}
private string text2;
public string Text2
{
get { return text2; }
set
{
text2 = value;
isSaved = true;
INotifyPropertyChanged("Text2");
INotifyPropertyChanged("IsSaved");
}
}
private bool isSaved = true;
public bool IsSaved
{
get { return isSaved; }
set
{
isSaved = value;
RaisePropertyChanged(() => Reg(() => IsSaved));
}
}
//INotifyPropertyChanged
}
<DataGrid Name="MyDataGrid" ItemsSource="{Binding MySource}"
SelectedItem="{Binding MyTarget, UpdateSourceTrigger=PropertyChanged}">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Visibility" Value="Visible"/>
<Style.Triggers>
<!-- for your other items-->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=MyDataGrid, Path=SelectedItem.IsSaved, UpdateSourceTrigger=PropertyChanged}" Value="false"/>
<Condition Binding="{Binding IsSaved}" Value="true"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Visibility" Value="Hidden"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
</DataGrid>
我找到了一种显示Row的方法,我希望你喜欢它:)
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<!-- for your other items-->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=MyDataGrid, Path=SelectedItem.IsSaved, UpdateSourceTrigger=PropertyChanged}" Value="false"/>
<Condition Binding="{Binding IsSaved}" Value="true"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="IsEnabled" Value="False"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
答案 1 :(得分:1)
第一步是创建一些基本框架,告诉您项目是否有变化。这可以使用MY_TYPE
类的另一个实例轻松实现,只需比较每个属性的值即可。
下一阶段是阻止用户更改所选项目,如果他们对当前对象进行了更改。如果您的SelectedTarget
属性绑定了正确的数据,那么您应该能够阻止用户更改当前行:
public MY_TYPE SelectedTarget
{
get { return selectedTarget; }
set
{
if (!SelectedTarget.HasChanges)
{
selectedTarget = value;
NotifyPropertyChanged("SelectedTarget");
}
}
}
最后,当用户保存当前项目时,您需要同步两个对象以表示不再有任何更改,然后用户将能够再次更改记录。