C# WPF中数据网格中的条件CanUserAddRows
假设我有一个组合框,如:C# WPF中数据网格中的条件CanUserAddRows,c#,wpf,xaml,datagrid,C#,Wpf,Xaml,Datagrid,假设我有一个组合框,如: <ComboBox SelectedValue="{Binding DataContext.CanUserAddMultipleRows, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}, Converter={Static
<ComboBox SelectedValue="{Binding DataContext.CanUserAddMultipleRows,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}},
Converter={StaticResource yesNoToBooleanConverter}}">
<ComboBoxItem>Yes</ComboBoxItem>
<ComboBoxItem>No</ComboBoxItem>
</ComboBox>
现在我有了一个数据网格:
<DataGrid Grid.Row="7" Grid.Column="1" Grid.ColumnSpan="2" AutoGenerateColumns="False"
CanUserAddRows="{Binding DataContext.CanUserAddMultipleRows,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}"
ItemsSource="{Binding DataContext.MyObject,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}">
<DataGrid.Columns>
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}"></DataGridTextColumn>
<DataGridTextColumn Header="Rate" Binding="{Binding Rate}"></DataGridTextColumn>
<DataGridTextColumn Header="Amount" Binding="{Binding Amount}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
现在,我希望在默认情况下为用户提供1行,这样,如果CanUserAddRows=false,那么他们也应该能够向DataGrid添加1项。若CanUserAddRows=true,那个么用户可以拥有他想要的任意数量的行
这件事可能很简单,但我对DataGrid还不熟悉。所以,我问了这个问题。在我的示例中,有一个bool类型的
MayUserAddRows
属性。如果MayUserAddRows==true
则用户可以添加尽可能多的记录,但如果MayUserAddRows==false
则他只能填充一条记录
还具有CanUserAddRows
属性,该属性直接与DataGrid.CanUserAddRows
的属性绑定
ViewModel中的属性通过NotificationObject实现接口。他有一个事件propertychangedventhandler(propertyName)
,通知通知属性。关键逻辑如下:
private void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals("MayUserAddRows"))
{
// The MayUserAddRows property is changed
if (MyViewModel.MayUserAddRows == true)
{
// Allow to add a lot of records
MyViewModel.CanUserAddRows = true;
}
if (MyViewModel.MayUserAddRows == false)
{
// Prohibit the addition
MyViewModel.CanUserAddRows = false;
// And add the empty row
AddEmptyRow(MyViewModel.MyCollection);
}
}
}
下面是一个完整的示例:
XAML
<Window x:Class="ConditionalCanUserAddRows.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="clr-namespace:ConditionalCanUserAddRows"
WindowStartupLocation="CenterScreen"
Title="MainWindow" Height="300" Width="325">
<Grid>
<CheckBox Content="{Binding Path=IsChecked,
RelativeSource={RelativeSource Mode=Self}}"
ContentStringFormat="May user add rows - {0}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsChecked="{Binding Path=MayUserAddRows}" />
<Button Content="Clear"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Click="Clear_Click" />
<DataGrid Name="SimpleDataGrid"
Width="200"
Height="200"
CanUserResizeColumns="False"
AutoGenerateColumns="False"
RowHeaderWidth="0"
CanUserAddRows="{Binding Path=CanUserAddRows, Mode=TwoWay}"
ItemsSource="{Binding Path=MyCollection}">
<DataGrid.Columns>
<DataGridTextColumn Width="1.5*"
Header="Name"
Binding="{Binding Path=Name}" />
<DataGridTextColumn Header="Age"
Width="1.5*"
FontSize="14"
Binding="{Binding Path=Age}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
public partial class MainWindow : Window
{
ViewModel MyViewModel = new ViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = MyViewModel;
MyViewModel.MyCollection = new ObservableCollection<Person>();
MyViewModel.MyCollection.Add(new Person()
{
Age = 22,
Name = "Nick",
});
MyViewModel.MyCollection.Add(new Person()
{
Age = 11,
Name = "Sam",
});
MyViewModel.MyCollection.Add(new Person()
{
Name = "Kate",
Age = 15,
});
AddEmptyRow(MyViewModel.MyCollection);
MyViewModel.PropertyChanged += new PropertyChangedEventHandler(MyViewModel_PropertyChanged);
}
private void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals("MayUserAddRows"))
{
if (MyViewModel.MayUserAddRows == true)
{
MyViewModel.CanUserAddRows = true;
}
if (MyViewModel.MayUserAddRows == false)
{
MyViewModel.CanUserAddRows = false;
AddEmptyRow(MyViewModel.MyCollection);
}
}
}
#region AddEmptyRow
private void AddEmptyRow(ObservableCollection<Person> collection)
{
collection.Add(new Person()
{
Name = "",
Age = 0,
});
}
#endregion
#region Clear
private void Clear_Click(object sender, RoutedEventArgs e)
{
MyViewModel.MyCollection.Clear();
}
#endregion
}
#region ViewModel
public class ViewModel : NotificationObject
{
#region MyCollection
public ObservableCollection<Person> MyCollection
{
get;
set;
}
#endregion
#region CanUserAddRows
private bool _canUserAddRows = false;
public bool CanUserAddRows
{
get
{
return _canUserAddRows;
}
set
{
_canUserAddRows = value;
NotifyPropertyChanged("CanUserAddRows");
}
}
#endregion
#region MayUserAddRows
private bool _mayUserAddRows = false;
public bool MayUserAddRows
{
get
{
return _mayUserAddRows;
}
set
{
_mayUserAddRows = value;
NotifyPropertyChanged("MayUserAddRows");
}
}
#endregion
}
#endregion
#region Model
public class Person
{
public string Name
{
get;
set;
}
public int Age
{
get;
set;
}
}
#endregion
#region NotificationObject
public class NotificationObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
#endregion
输出
<Window x:Class="ConditionalCanUserAddRows.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="clr-namespace:ConditionalCanUserAddRows"
WindowStartupLocation="CenterScreen"
Title="MainWindow" Height="300" Width="325">
<Grid>
<CheckBox Content="{Binding Path=IsChecked,
RelativeSource={RelativeSource Mode=Self}}"
ContentStringFormat="May user add rows - {0}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsChecked="{Binding Path=MayUserAddRows}" />
<Button Content="Clear"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Click="Clear_Click" />
<DataGrid Name="SimpleDataGrid"
Width="200"
Height="200"
CanUserResizeColumns="False"
AutoGenerateColumns="False"
RowHeaderWidth="0"
CanUserAddRows="{Binding Path=CanUserAddRows, Mode=TwoWay}"
ItemsSource="{Binding Path=MyCollection}">
<DataGrid.Columns>
<DataGridTextColumn Width="1.5*"
Header="Name"
Binding="{Binding Path=Name}" />
<DataGridTextColumn Header="Age"
Width="1.5*"
FontSize="14"
Binding="{Binding Path=Age}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
public partial class MainWindow : Window
{
ViewModel MyViewModel = new ViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = MyViewModel;
MyViewModel.MyCollection = new ObservableCollection<Person>();
MyViewModel.MyCollection.Add(new Person()
{
Age = 22,
Name = "Nick",
});
MyViewModel.MyCollection.Add(new Person()
{
Age = 11,
Name = "Sam",
});
MyViewModel.MyCollection.Add(new Person()
{
Name = "Kate",
Age = 15,
});
AddEmptyRow(MyViewModel.MyCollection);
MyViewModel.PropertyChanged += new PropertyChangedEventHandler(MyViewModel_PropertyChanged);
}
private void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals("MayUserAddRows"))
{
if (MyViewModel.MayUserAddRows == true)
{
MyViewModel.CanUserAddRows = true;
}
if (MyViewModel.MayUserAddRows == false)
{
MyViewModel.CanUserAddRows = false;
AddEmptyRow(MyViewModel.MyCollection);
}
}
}
#region AddEmptyRow
private void AddEmptyRow(ObservableCollection<Person> collection)
{
collection.Add(new Person()
{
Name = "",
Age = 0,
});
}
#endregion
#region Clear
private void Clear_Click(object sender, RoutedEventArgs e)
{
MyViewModel.MyCollection.Clear();
}
#endregion
}
#region ViewModel
public class ViewModel : NotificationObject
{
#region MyCollection
public ObservableCollection<Person> MyCollection
{
get;
set;
}
#endregion
#region CanUserAddRows
private bool _canUserAddRows = false;
public bool CanUserAddRows
{
get
{
return _canUserAddRows;
}
set
{
_canUserAddRows = value;
NotifyPropertyChanged("CanUserAddRows");
}
}
#endregion
#region MayUserAddRows
private bool _mayUserAddRows = false;
public bool MayUserAddRows
{
get
{
return _mayUserAddRows;
}
set
{
_mayUserAddRows = value;
NotifyPropertyChanged("MayUserAddRows");
}
}
#endregion
}
#endregion
#region Model
public class Person
{
public string Name
{
get;
set;
}
public int Age
{
get;
set;
}
}
#endregion
#region NotificationObject
public class NotificationObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
#endregion
MayUserAddRows=“False”
MayUserAddRows=“True”
在VisualStudio2010下编译的项目,这个例子完全符合MVVM风格
此项目可用
回答得好!谢谢我想再增加3个功能。1) 用户点击清除按钮。然后他选中复选框,此时添加了两行。1具有默认值,另一个为空。当时,我不希望用户有一行带有默认值。2) 当用户取消选中该复选框时,我想清除所有行以及“年龄单元格”列应包含所有年龄的总和。例如,在您答案的最后一张图片中,如果我取消选中复选框,则只有一行应该在那里,并且年龄应该包含1491(因为22+11+15+666+777=1491)。3)我还希望有一个只有两个值的新DataGridComboBoxColumn。i、 e.1)继续2)列表结束。如果用户选择“继续”,则他应该能够在当前行中添加姓名和年龄等详细信息,并且应该能够在填写当前行的详细信息后添加新行。否则,不应允许他在当前行中填写更多详细信息,如姓名和年龄,并且不应在该行之后创建新行。@Vishal:这就是我必须实现的全部功能?对不起,我只做了有问题的事,你自己能做的一切。此外,你必须先在问题中写出来。