пытаюсь постигнуть MVVM. У меня есть поля и свойства(подключенные к XAML форме приложения)
В классе MainWindowViewModel:ViewModel
private double _dL;
public double dL
{
get => _dL;
set => Set(ref _dL, value);
}
Соотвественно в разметке XAML привязано поле dL.
Класс ViewModel реализуется так:
internal abstract class ViewModel : INotifyPropertyChanged, IDisposable
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string PropertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
protected virtual bool Set<T>(ref T field, T value, [CallerMemberName] string PropertyName = null)
{
if (Equals(field, value)) return false;
field = value;
OnPropertyChanged(PropertyName);
return true;
}
public void Dispose()
{
Dispose(true);
}
private bool _Disposed;
protected virtual void Dispose(bool Disposing)
{
if (!Disposing || _Disposed) return;
_Disposed = true;
}
}
Я раньше думал, что поля мне служат для внутренней логики и расчетов, а свойства для отображения на форме. Например, мне внутри программы нужно провести точные расчеты в вывести на форме - округленные значения. я в классе MainWindowViewModel что то считаю с _dL
_dL = 3.14*255/360+0.1;
То есть получаю точные значения без округления, а затем для формы пишу
dL = Math.Round(_dL,3); // и на форме отобразиться округленное значение
Но проблема в том, что если мне в дальнейшем нужно будет опять использовать для расчетов _dL (точное значение) - оно уже исчезло, и у меня только округленное свойство есть.
Как быть? Кроме очевидного - там где мне надо снова - опять считать _dL ?
{Binding dL, StringFormat=F3}– aepot Aug 23 '21 at 10:16_dLнужен вам для того, чтоб не получить цикличный вызов свойства, что приведет кStackOverflowException. То есть, если бы вы указали, к примеруget => dL;, то при получении значения у свойства, оно пошло бы получать его уdL(у самого себя), что привело бы опять к вызовуgetи опять, и опять. Вот поэтому, в свойствах данные хранят в отдельном, приватном поле. Так что, расценивайте их как одно целое и обращайтесь лишь к свойству, ведь если вы обратитесь к полю, то вся логика, прописанная у свойства не будет выполнена, что в вашем случае приведет к отсутствию обновления данных у окна. – EvgeniyZ Aug 23 '21 at 10:21{Binding SomeProp, StringFormat = нужныйВид}, если это не позволит вам подобное сделать, то делайте конвертор и указывайте его также, в привязке. – EvgeniyZ Aug 23 '21 at 10:26смысл разделения логики и представления- В удобстве? В тестируемости? В разделении тех же обязанностей? В производительности? Например, вы можете отдать разработку View другому человек, который совершенно не знает про то, что будет у вас в логике, ему надо лишь знать, что будет некое свойство с, допустим, процентом загрузки, он на может сделать ProgressBar и стилизировать его, не дожидаясь логики. Посмотрите например это, там все отдельно друг от друга, в своей библиотеки. – EvgeniyZ Aug 23 '21 at 10:34То есть для каждой пары - свойство-поле - добавляю еще одно приватное поле- ну если вам надо хранить старые данные, да, вам нужен еще один объект, в который будете их помещать. Но еще раз подумайте про View часть, ваше округление легко сделать на его уровне... – EvgeniyZ Aug 23 '21 at 10:36myTextBox.Text = "SomeText")? Малейшее изменение вызывало бы у вас негативные чувства и кучу боли. Так что старайтесь делать все менее связанным друг с другом. – EvgeniyZ Aug 23 '21 at 10:45StringFormatмало) и в нем прописываете все нужные округления, будет "приятный глазу вид". – EvgeniyZ Aug 23 '21 at 11:12Через него как то получается для отображения в привязке делать одну конвертацию, а для работы в коде - исходные не округленные значения? Правильно?
– Евгений Федоров Aug 23 '21 at 11:20ConvertиConvertBack, где первый преобразует значение свойства в "читаемое" для контрола, а второй наоборот, значение контрола преобразует обратно в нужный формат для свойства (напримерTextBox, пользователь написал "один", а вам надо получить1). Вам надо лишь отобразить, то есть толькоConvert. Чтоб не захламлять XAML, можете использовать трюк, сMarkupExtension(как например показано тут). – EvgeniyZ Aug 23 '21 at 11:31return value is double number ? number.ToString("0.###") : value.ToString();либо без конвертераStringFormat=0.###можно попробовать. – aepot Aug 23 '21 at 12:13Еще раз всем спасибо!!!
– Евгений Федоров Aug 23 '21 at 12:59<Run>ΔL = </Run>вStringFormatперенесите, более читаемо и приятней будет. Хотя на вкус и цвет.. – EvgeniyZ Aug 23 '21 at 16:16Mode=TwoWay- лишнее. Вы ж не к текстбоксу привязываетесь, где и данные могут меняться прямо в интерфейсе, оставьтеMode=OneWayили вообще уберите. – aepot Aug 24 '21 at 11:38