There is a certain structure, for example NotMyStruct . There is no direct access to the structure code. There is a class MyClass , in which there is an instance of this structure called valStruct . In struktru there is a field of a type

 uint? Value { get; set; } = null; 

There is also a UserControl in the bark that is a ListBox with a binding to a DataConext . Objects are added to this ListBox from ObservableCollection via binding. It all works.

Further. Through DataTemplate describe something like this style:

 <DataTemplate DataType="{x:Type local:MyClass}"> <Grid> <Slider Value="{Binding valStruct.Value, Converter={StaticResource DoubleToUintConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> </Grid> </DataTemplate> 

Ps. Converter does not issue errors. Essentially just converts via System.Convert

The problem is that the Value value with and remains null when the slider moves. How to make such a binding?

UPD

 [ValueConversion(typeof(double), typeof(uint?))] public class DoubleToUintConverter : MarkupExtension, IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return System.Convert.ToUInt32(value); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return System.Convert.ToDouble(value); } } 
  • Show Converter - Pavel Mayorov
  • @PavelMayorov added - BwehaaFox
  • valStruct - judging by the name, is it not public? In this case, it will not work correctly. - icebat
  • @icebat valStruct 'is an instance of the NotMyStruct structure, It can be quietly public. The problem is that NotMyStruct sealed structure. OnPropertyChanged() implementing OnPropertyChanged() inside is not possible, but I don’t know how to do something else. - BwehaaFox
  • Can then just wrap valStruct.Value into a separate MyClass with PropertyChanged support and do all operations with Value through it? - icebat

1 answer 1

There are a lot of problems in your code.

To begin with, NotMyStruct is a typically model data structure that, of course, does not implement INotifyPropertyChanged .

Therefore, your code will not be able to catch changes in this structure, only send changes from the UI to it.

Then, your converter converts in the wrong direction. Should he convert from uint? in double , and you have the opposite. Fix the converter:

 public class NullableUintToDoubleConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return (double)((uint?)value ?? 0); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return (uint)(double)value; } } 

Farther. Your Slider returns values ​​from 0 to 1, because Maximum not set. When rounding to integer, a pure zero is obtained, so the Binding writes the value 0 to the property. To fix this, put the maximum in uint.MaxValue :

 <Slider Value="{Binding valStruct.Value, Converter={StaticResource NullableUintToDoubleConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Minimum="0" Maximum="4294967295"/> 

Then, the big problem: the mutable structure! Mutable structures are evil. Values ​​do not fall into the structure through binding to valStruct.Value , and here's why.

How does valStruct.Value ? First, the class MyClass , which is a DataContext ', is searched for the public property valStruct , and its value is obtained through a getter. Because valStruct is a structure, you get a copy of the value ! When the value of Value is read from this copy, there is no problem: the value in the copy is the same as in the original. But when the value of the Value recorded through the same Binding , then only a copy of valStruct , and not the original!

How to fix it? For example, you can wrap this property:

 public NotMyStruct valStruct { get; set; } public uint? valStructValueBindable { get { return valStruct.Value; } set { valStruct = new NotMyStruct() { Value = value }; } } 

(note that in the setter we created the property again!)

Or so:

 NotMyStruct valStruct; public uint? valStructValueBindable { get { return valStruct.Value; } set { valStruct.Value = value; } } 

(in this case, you write directly to the structure, not to its copy).

In doing so, your XAML gets the look

 <Slider Value="{Binding valStructValueBindable, Converter={StaticResource NullableUintToDoubleConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Minimum="0" Maximum="4294967295"/> 

Voila, it works.

  • Thank. Just notice that by default, my Maximum was 100, since the slider is custom. - BwehaaFox
  • @BwehaaFox: Please! Hope it helped. - VladD
  • How do I understand each field in the structure? Or maybe there is a thread specialized library or subroutine similar to KindOfMagic - BwehaaFox
  • @BwehaaFox: I'm afraid so. If there are a lot of fields, it may be worthwhile to write a code generator so that it is not manually. - VladD