假设我有一个ComboBox,如:
<ComboBox SelectedValue="{Binding DataContext.CanUserAddMultipleRows,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}},
Converter={StaticResource yesNoToBooleanConverter}}">
<ComboBoxItem>Yes</ComboBoxItem>
<ComboBoxItem>No</ComboBoxItem>
</ComboBox>
这是转换器:
public class YesNoToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!(value == null || value == DependencyProperty.UnsetValue))
{
if ((bool)value == true)
{
return "Yes";
}
else
{
return "No";
}
}
else
{
return "No";
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (!(value == null || value == DependencyProperty.UnsetValue))
{
if (((ComboBoxItem)value).Content.ToString() == "Yes")
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
}
现在我有一个DataGrid:
<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的新手。所以,我问了这个问题。
答案 0 :(得分:2)
在我的示例中, bool 类型有MayUserAddRows
属性。如果MayUserAddRows == true
则用户可以添加任意数量的记录,但如果MayUserAddRows == false
则他只能填写一条记录。
还具有CanUserAddRows
属性,该属性直接与DataGrid.CanUserAddRows
的属性绑定。
ViewModel中的属性通过NotificationObject实现INotifyPropertyChanged
接口。他有一个事件PropertyChangedEventHandler(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>
<强> Code-behind
强>
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
<强> Output
强>
MayUserAddRows="False"
MayUserAddRows="True"
在Visual Studio 2010下编译的项目,此示例完全符合MVVM样式。
此项目可用
here