WPF binding: if the property contains a value path

I have an expander with several text blocks in the top pane that I use to give a title and a snippet of key information.

Ideally, I want to set the path to a key piece of information, but I can’t figure out how to link the binding path to another path (I apologize if I do not make much sense!)

In the next xaml, the first bit works, the second bit is what I'm struggling with.

<TextBlock Text="{Binding Path=Header.Title}"/> <TextBlock Text="{Binding Path={Binding Path=Header.KeyValuePath}}"/> 

KeyValuePath may contain something like "Vehicle.Registration" or "Supplier.Name" depending on the model.

Can someone point me in the right direction please? Any help gratefully received!

+4
source share
2 answers

I don't think this can be done in pure XAML ... The path is not a DependencyProperty (and Binding is not a DependencyObject anyway), so it cannot be a binding target

You can change the binding in the code instead

+3
source

I did not find a way to do this in XAML, but I did it in code. Here is my approach.

Firstly, I wanted to do this for all items in an ItemsControl . So I had XAML:

 <ListBox x:Name="_events" ItemsSource="{Binding Path=Events}"> <ListBox.ItemTemplate> <DataTemplate DataType="{x:Type Events:EventViewModel}"> <TextBlock Name="ActualText" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox> 

Then, in the code behind the construct, I subscribe to ItemContainerGenerator :

 InitializeComponent(); _events.ItemContainerGenerator.StatusChanged += OnItemContainerGeneratorStatusChanged; 

This method is as follows:

 private void OnItemContainerGeneratorStatusChanged(object sender, EventArgs e) { if (_events.ItemContainerGenerator.Status!=GeneratorStatus.ContainersGenerated) return; for (int i = 0; i < _viewModel.Events.Count; i++) { // Get the container that wraps the item from ItemsSource var item = (ListBoxItem)_events.ItemContainerGenerator.ContainerFromIndex(i); // May be null if filtered if (item == null) continue; // Find the target var textBlock = item.FindByName("ActualText"); // Find the data item to which the data template was applied var eventViewModel = (EventViewModel)textBlock.DataContext; // This is the path I want to bind to var path = eventViewModel.BindingPath; // Create a binding var binding = new Binding(path) { Source = eventViewModel }; textBlock.SetBinding(TextBlock.TextProperty, binding); } } 

If you have only one element to set the binding, then the code will be a little easier.

 <TextBlock x:Name="_text" Name="ActualText" /> 

And in the code behind:

 var binding = new Binding(path) { Source = bindingSourceObject }; _text.SetBinding(TextBlock.TextProperty, binding); 

Hope this helps someone.

+1
source

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


All Articles