将TextBox绑定到Code Behind

时间:2016-08-25 12:20:14

标签: c# wpf listbox

我有一个带有TextBox和Listbox的MainWindow。 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中选择的任何项目。但是,当我在文本框中键入一些文本时,ListBox中的相应项目不会更改。

我搜索了很多关于UpdateSourceTrigger,绑定等的内容,但几乎所有这些都是关于使用XAML的,我发现的任何内容都不符合要求。我做错了什么?

2 个答案:

答案 0 :(得分:1)

这不会起作用,因为你绑定了一个字符串。因此没有触发INotifyPropertyChanged事件,因此列表没有注意到它已更新。尝试使用字符串将列表绑定到某个复杂对象:

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);

答案 1 :(得分:0)

你的问题是你不告诉你的UI字符串已经改变了。您可以使用此界面INotifyPropertyChanged执行此操作。如果您有兴趣,可以查看此answer,然后进入MVVM

但是对于后面的代码中的一个简单的解决方案,我会在XAML中推荐依赖性属性和绑定,就像在这个例子中一样。

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");

        }

    }
}

如果ListBox文字与&#39; ItemsSource&#39;中的项目不匹配,它也会取消选择TextBox条目。 ListBox

编辑:更多评论