Reputation: 6368
Suppose I have a ComboBox like :
<ComboBox SelectedValue="{Binding DataContext.CanUserAddMultipleRows,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}},
Converter={StaticResource yesNoToBooleanConverter}}">
<ComboBoxItem>Yes</ComboBoxItem>
<ComboBoxItem>No</ComboBoxItem>
</ComboBox>
Here is the Converter :
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;
}
}
}
Now I have a 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>
Now I want to provide 1 row by default to the users, so that if CanUserAddRows = false, then also they should be able to add 1 item to DataGrid. If CanUserAddRows = true, then user can have any number of rows he wants.
This thing might be simple but I am new to DataGrid. So, i asked this question.
Upvotes: 2
Views: 1479
Reputation: 22702
In my example, there is a MayUserAddRows
property of bool type. If MayUserAddRows == true
then User can add as many records, but if MayUserAddRows == false
then he will be able to fill only one record.
Also has CanUserAddRows
property, which directly Binding with the property of DataGrid.CanUserAddRows
.
Properties that are in the ViewModel implement the INotifyPropertyChanged
interface via NotificationObject. He has an event PropertyChangedEventHandler(propertyName)
which informs on notification properties. The key logic is here:
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);
}
}
}
Below is a full example:
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"
Project compiled under the Visual Studio 2010, this example is fully fits the MVVM style.
This project available
here
Upvotes: 2