0

I want to change the binding path SomeProperty to another at runtime. And the PropertyName can be any string ,so I can't set it before it running. how to do this?

I tried "FindName" method to find tb1 but it's not work.

Partical code :

<ListBox>
 <ListBox.ItemTemplate>
  <DataTemplate>
   <TextBox Name="tb1" Text="{Binding Path=SomeProperty}"/>
  </DataTemplate>
 </ListBox.ItemTemplate>
</ListBox>

2 Answers 2

2

Due to the lack of context, let's try to establish one.

Assuming your ListBox is binding to a Person list with FirstName and LastName property, initial binding would be FirstName and you want to change it to LastName during runtime when clicking on a button.

This is how you can achieve it.

View

<ListBox Name="LstBx" ItemsSource="{Binding PersonList}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBox Name="tb1" Text="{Binding Path=FirstName}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

<Button Click="Button_Click" Width="100" Height="20" Content="Change Binding"/>

CodeBehind

public List<Person> PersonList { get; set; } = new List<Person>
{
    new Person { FirstName = "ABC", LastName = "123" },
    new Person { FirstName = "DEF", LastName = "456" },
    new Person { FirstName = "GHI", LastName = "789" }
};

public MainWindow()
{
    InitializeComponent();
    DataContext = this;
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    foreach (var person in PersonList)
    {
        var listBoxItem = LstBx.ItemContainerGenerator.ContainerFromItem(person);
        var contentPresenter = FindVisualChild<ContentPresenter>(listBoxItem);
        var target = contentPresenter.ContentTemplate.FindName("tb1", contentPresenter) as TextBox;

        if (target != null)
        {
            var binding = new Binding
            {
                // Remember each ListBoxItem's DataContext is the individual item 
                // in the list, not the list itself.
                Source = person, 
                Path = new PropertyPath(nameof(Person.LastName)),
                // Depends on what you need.
                //Mode = BindingMode.TwoWay,
                //UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
            };

            BindingOperations.SetBinding(target, TextBox.TextProperty, binding);
        }
    }
}

// Available from MSDN
private Child FindVisualChild<Child>(DependencyObject obj) where Child : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        var child = VisualTreeHelper.GetChild(obj, i);
        if (child != null && child is Child)
        {
            return (Child)child;
        }
        else
        {
            var childOfChild = FindVisualChild<Child>(child);

            if (childOfChild != null) { return childOfChild; }
        }
    }
    return null;
}
Sign up to request clarification or add additional context in comments.

Comments

2

Maybe you're simply looking for "DisplayMemberPath"?

<ListBox ItemsSource="{Binding Items}" DisplayMemberPath="SomeProperty" />

You cannot mix it with DataTemplates but in your example you didn't really need it.

You can create a normal binding for this property:

<StackPanel>
    <ListBox ItemsSource="{Binding Items}"
        DisplayMemberPath="{Binding ElementName=DisplayPathText, Path=Text}" />
    <TextBox Name="DisplayPathText" Text="SomeProperty" />
</StackPanel>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.