Alert: , , ViewModels.
semplicity FeeTypes FeeType
:
public class FeeType
{
public decimal Min { get; set; }
public decimal Max { get; set; }
public string Name { get; set; }
public static readonly FeeType[] List = new[]
{
new FeeType { Min = 0, Max = 10, Name = "Type1", },
new FeeType { Min = 2, Max = 20, Name = "Type2", },
};
}
ViewModel Grid. .
public class RowViewModel : INotifyPropertyChanged, INotifyDataErrorInfo
{
public RowViewModel()
{
_errorFromProperty = new Dictionary<string, string>
{
{ nameof(Fee), null },
{ nameof(Amount), null },
};
PropertyChanged += OnPropertyChanged;
}
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch(e.PropertyName)
{
case nameof(Fee):
OnFeePropertyChanged();
break;
case nameof(Amount):
OnAmountPropertyChanged();
break;
default:
break;
}
}
private void OnFeePropertyChanged()
{
if (Fee == null)
_errorFromProperty[nameof(Fee)] = "You must select a Fee!";
else
_errorFromProperty[nameof(Fee)] = null;
NotifyPropertyChanged(nameof(Amount));
}
private void OnAmountPropertyChanged()
{
if (Fee == null)
return;
if (Amount < Fee.Min || Amount > Fee.Max)
_errorFromProperty[nameof(Amount)] = $"Amount must be between {Fee.Min} and {Fee.Max}!";
else
_errorFromProperty[nameof(Amount)] = null;
}
public decimal Amount
{
get { return _Amount; }
set
{
if (_Amount != value)
{
_Amount = value;
NotifyPropertyChanged();
}
}
}
private decimal _Amount;
public FeeType Fee
{
get { return _Fee; }
set
{
if (_Fee != value)
{
_Fee = value;
NotifyPropertyChanged();
}
}
}
private FeeType _Fee;
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region INotifyDataErrorInfo
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public bool HasErrors
{
get
{
return _errorFromProperty.Values.Any(x => x != null);
}
}
public IEnumerable GetErrors(string propertyName)
{
if (string.IsNullOrEmpty(propertyName))
return _errorFromProperty.Values;
else if (_errorFromProperty.ContainsKey(propertyName))
{
if (_errorFromProperty[propertyName] == null)
return null;
else
return new[] { _errorFromProperty[propertyName] };
}
else
return null;
}
private Dictionary<string, string> _errorFromProperty;
#endregion
}
native DataGrid
, Telerik:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Rows}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Amount}"/>
<DataGridComboBoxColumn SelectedItemBinding="{Binding Fee, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{x:Static local:FeeType.List}"
DisplayMemberPath="Name"
Width="200"/>
</DataGrid.Columns>
</DataGrid>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Rows = new List<RowViewModel>
{
new RowViewModel(),
new RowViewModel(),
};
DataContext = this;
}
public List<RowViewModel> Rows { get; }
}
FeeType
Min
Max
, INotifyPropertyChanged
, .
"MVVM", "ViewModels", " " .., , WPF, , MVVM. , .