XAML dictionary binding with Type key

I am trying to bind to Dictionary<Type,string> via xaml.

The problem is that the index [] in the Binding markup extension interprets it as a string. Is there some kind of "unescape-sequence" for this case?

 <TextBox Text="{Binding theDictionary[{x:Type ns:OnePrettyType}]}" /> 

(Binding does not work because {x:Type ns:OnePrettyType} sent as a string)

+6
source share
2 answers

If the pointer is of a specific type, the conversion must be done automatically for this to work:

 {Binding theDictionary[ns:OnePrettyType]} 

If you need an explicit interpretation, you can try "translation" as follows:

 {Binding theDictionary[(sys:Type)ns:OnePrettyType]} 

(where sys , of course, maps to the System namespace)

It will be a theory, but all this will not work. First of all, if you use the Binding constructor, which takes the path, the casting will be ignored, since it uses a specific PropertyPath constructor in a specific way. You will also get a binding error:

System.Windows.Data error: 40: BindingExpression path error: property '[]' not found on 'object' '' Dictionary`2 '

You will need to make the PropertyPath construct through the type converter, avoiding the Binding constructor:

 {Binding Path=theDictionary[(sys:Type)ns:OnePrettyType]} 

Now this is likely to throw an exception:

{"The path pointer parameter has a value that cannot be resolved for the specified type: 'sys: Type'"}

So, unfortunately, the default type conversion does not occur. Then you could build a PropertyPath in XAML and make sure that the type is passed, but the class is not intended to be used in XAML and will throw an exception, if you try, is also very unsuccessful.

One way could be to create a markup extension that performs the construct, for example

 [ContentProperty("Parameters")] public class PathConstructor : MarkupExtension { public string Path { get; set; } public IList Parameters { get; set; } public PathConstructor() { Parameters = new List<object>(); } public PathConstructor(string path, object p0) { Path = path; Parameters = new[] { p0 }; } public override object ProvideValue(IServiceProvider serviceProvider) { return new PropertyPath(Path, Parameters.Cast<object>().ToArray()); } } 

Which one can be used as follows:

 <Binding> <Binding.Path> <me:PathConstructor Path="theDictionary[(0)]"> <x:Type TypeName="ns:OnePrettyType" /> </me:PathConstructor> </Binding.Path> </Binding> 

or how is it

 {Binding Path={me:PathConstructor theDictionary[(0)], {x:Type ns:OnePrettyType}}} 
+11
source

update: I leave this for reference for the Bindings extension

 <Grid Width="{my:ParameterBinding {Binding [(0)],Source={x:Static my:SettingsService.Current}, Mode=TwoWay},{x:Type my:LeftPanelWidthSetting}}"/> 

and what is the code behind

 [ContentProperty( "Parameters" )] public class ParameterBinding : MarkupExtension { public Binding Binding { get; set; } public IList Parameters { get; set; } public ParameterBinding() { Parameters = new List<object>(); } public ParameterBinding( Binding b, object p0 ) { Binding = b; Parameters = new []{p0}; } public override object ProvideValue( IServiceProvider serviceProvider ) { Binding.Path = new PropertyPath( Binding.Path.Path, Parameters.Cast<object>().ToArray() ); return Binding.ProvideValue(serviceProvider); } } 

this will be extensible to support additional parameters in the built-in syntax with additional constructors. I still left the option to add a lot of parameters with advanced element syntax.

thanks to HB for inspiring this

+2
source

Source: https://habr.com/ru/post/908945/


All Articles