在后台代码中将文本框绑定到列表框
本文关键字:绑定 列表 文本 后台 代码 | 更新日期: 2023-09-27 18:04:00
我有一个主窗口与文本框和列表框。TextBox是双向绑定到ListBox的,ListBox是由BindingList填充的。
InitializeComponent();
productNames = new BindingList<string>(/*some content*/);
Binding binding = new Binding();
binding.Mode = BindingMode.TwoWay;
binding.Path = new PropertyPath("SelectedItem");
binding.ElementName = "listBox1";
textBox1.SetBinding(TextBox.TextProperty, binding);
listBox1.ItemsSource = productNames;
到目前为止,一切顺利:ListBox很好地显示了列表的内容,TextBox忠实地显示了在ListBox中选择的任何项。但是,当我在文本框中输入一些文本时,列表框中相应的项不会改变。
我在谷歌上搜索了很多关于UpdateSourceTrigger、binding等的内容,但几乎所有内容都是关于使用XAML的,我没有找到符合要求的内容。我做错了什么?
这不起作用,因为您绑定的是字符串。所以没有INotifyPropertyChanged-events被触发,所以列表没有注意到它被更新了。尝试用字符串将列表绑定到一些复杂的对象:
class CompexObject : INotifyPropertyChanged
{
private string myString;
public event PropertyChangedEventHandler PropertyChanged;
public string MyString
{
get { return this.myString; }
set
{
this.myString = value;
this.PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(nameof(MyString)));
}
}
}
然后将列表设置为:
productNames = new BindingList<ComplexObject>(/*some content*/);
你的绑定应该改为:
Binding binding = new Binding();
binding.Mode = BindingMode.TwoWay;
binding.Path = new PropertyPath("SelectedItem.MyString");
binding.ElementName = "listBox1";
textBox1.SetBinding(TextBox.TextProperty, binding);
你的问题是你没有告诉你的UI字符串已经改变了。你可以用这个接口INotifyPropertyChanged
来做。如果你感兴趣的话,看看这个答案,也许你会进入MVVM
。
但是对于后面代码的简单解决方案,我建议在XAML
中使用依赖属性和绑定,就像这个例子一样。
<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Test"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525"
Name="myWindow">
<StackPanel>
<ListBox ItemsSource="{Binding ElementName=myWindow, Path=ItemCollection, Mode=OneWay}"
SelectedItem="{Binding ElementName=myWindow, Path=SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</ListBox>
<TextBox Text="{Binding ElementName=myWindow, Path=TextBoxText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
背后的代码:
namespace Test
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
/// <summary>
/// Store your ListBox entrys here
/// </summary>
public ObservableCollection<string> ItemCollection
{
get { return (ObservableCollection<string>)GetValue(ItemCollectionProperty); }
set { SetValue(ItemCollectionProperty, value); }
}
// Using a DependencyProperty as the backing store for ItemCollection. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ItemCollectionProperty =
DependencyProperty.Register("ItemCollection", typeof(ObservableCollection<string>), typeof(MainWindow), new PropertyMetadata(new ObservableCollection<string>()));
/// <summary>
/// This binds to the TextBox text
/// </summary>
public string TextBoxText
{
get { return (string)GetValue(TextBoxTextProperty); }
set { SetValue(TextBoxTextProperty, value); }
}
// Using a DependencyProperty as the backing store for TextBoxText. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TextBoxTextProperty =
DependencyProperty.Register("TextBoxText", typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty, OnTextBoxTextChanged));
private static void OnTextBoxTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
MainWindow self = d as MainWindow;
if(self != null)
{
self.OnTextBoxTextChanged(args.NewValue.ToString());
}
}
private void OnTextBoxTextChanged(string newValue)
{
if (this.ItemCollection.Contains(newValue))
{
this.SelectedItem = newValue;
}
else
{
this.SelectedItem = null;
}
}
/// <summary>
/// This binds to the selected item of your ListBox
/// </summary>
public string SelectedItem
{
get { return (string)GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
// Using a DependencyProperty as the backing store for SelectedItem. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register("SelectedItem", typeof(string), typeof(MainWindow), new PropertyMetadata(string.Empty, OnSelectedItemChanged));
private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
MainWindow self = d as MainWindow;
if (self != null)
{
self.OnSelectedItemChanged(args.NewValue as string);
}
}
private void OnSelectedItemChanged(string newValue)
{
if (!this.TextBoxText.Equals(newValue) && !string.IsNullOrEmpty(newValue))
{
this.TextBoxText = newValue;
}
}
public MainWindow()
{
InitializeComponent();
this.ItemCollection.Add("Name 1");
this.ItemCollection.Add("Name 2");
this.ItemCollection.Add("Name 3");
this.ItemCollection.Add("Name 4");
this.ItemCollection.Add("Name 5");
}
}
}
当TextBox
文本与ListBox
的"ItemsSource"中的项目不匹配时,它也取消选择ListBox
条目。
编辑:更多评论