【问题标题】:Setter not triggering as user types into TextBox当用户键入 TextBox 时,Setter 未触发
【发布时间】:2020-02-01 13:19:02
【问题描述】:

我正在尝试根据用户在文本框中键入的内容来过滤列表。但是,当用户在框中输入内容时,什么都没有发生。由于我一直在调试,我已在此绑定的设置器上放置断点,但它们不会触发。

文本框定义:

<TextBox HorizontalAlignment="Center" Text="{Binding TESTSerialNumbSearchTerm, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" ToolTip="Filter Part Number" Width="180"/>

ViewModel 绑定:

public String TESTSerialNumbSearchTerm
{
    get
    {
        return serialNumbSearchTerm;
    }
    set
    {
        if (serialNumbSearchTerm != value)
        {
            serialNumbSearchTerm = value;
            VisibleProfiles = FilterList(VisibleProfiles, Tuple.Create("serialNumber", value));
            OnPropertyChanged(nameof(VisibleProfiles));
            OnPropertyChanged(nameof(TESTSerialNumbSearchTerm));
        }
    }
}

网格定义,带有 ItemSource:

<DataGrid MaxHeight="400" Grid.Row="0" ItemsSource="{Binding VisibleProfiles}" SelectedItem="{Binding SelectedProfile}" SelectionMode="Single" IsReadOnly="True" AutoGenerateColumns="False" VerticalScrollBarVisibility="Visible">

FilterList 方法:

public List<DongleProfile> FilterList(List<DongleProfile> inputList, Tuple<string, string> filter)
{
    List<DongleProfile> newList = new List<DongleProfile>();
    foreach (DongleProfile item in inputList)
    {
        switch (filter.Item1)
        {
            case "serialNumber":
                if (item.SerialNumberPrefix.Contains(filter.Item2))
                {
                    newList.Add(item);
                }
                break;
                // Similar cases
        }
    }
    return newList;
}

【问题讨论】:

  • 请添加FilterList 方法并列出绑定/xaml 代码
  • VisibleProfiles 是如何定义的?努力做到ObservableCollection
  • 曾是一个列表,已将其更改为 ObservableCollection 但没有更改
  • 看看CollectionViewSource这个thread中的类
  • VisibleProfiles 中的项目以ListObservableCollection 的形式出现在网格中。我已经在 TextBox 值的设置器上设置了一个断点,并且它永远不会中断,就好像没有输入任何内容一样

标签: c# wpf


【解决方案1】:

如果TextBox 位于DataGrid 中,您可以使用RelativeSource 绑定到视图模型的属性:

<TextBox HorizontalAlignment="Center" 
         Text="{Binding DataContext.TESTSerialNumbSearchTerm, UpdateSourceTrigger=PropertyChanged, 
            RelativeSource={RelativeSource AncestorType=DataGrid}}" 
         ToolTip="Filter Part Number" Width="180"/>

【讨论】:

  • 想在接受之前进行测试,但这非常有效。两天的问题解决了,非常感谢。
【解决方案2】:

试试下面的思路:

用于过滤文本框的公共字段

public string md_FilterString
        {
            get { return _FilterString; }
            set
            {
                if (_FilterString != value)
                {
                    _FilterString = value;
                    mf_MakeView();
                    OnPropertyChanged("md_FilterString");
                }
            }
        }

数据网格绑定的公共字段:

public ICollectionView md_LogEntriesStoreView { get; private set; }

XAML:

..
<TextBox Grid.Column="1"
                     Text="{Binding md_FilterString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                     Height="22"
                     HorizontalAlignment="Stretch"
                     Margin="0,0,0,0"
                     Name="textBoxFilter"
                     VerticalAlignment="Center"/>
..
<DataGrid ItemsSource="{Binding md_LogEntriesStoreView, UpdateSourceTrigger=PropertyChanged}"
..
</DataGrid>

mf_MakeView func 配置集合 md_LogEntriesStoreView 的组成:

 private void mf_MakeView()
        {
            if (d_Items== null) return;
            md_LogEntriesStoreView = CollectionViewSource.GetDefaultView(d_Items);
            md_LogEntriesStoreView.Filter = mf_UserFilter;
            OnPropertyChanged("md_LogEntriesStoreView");
        }

其中 d_Items - 直接是您的 observable 集合中将显示在控件数据网格中的元素

过滤功能 (mf_UserFilter) 以一般方式呈现给包含文本字段的对象。您可以将其替换为适合您目标的版本以进行优化:

private bool mf_UserFilter(object item)
        {
            string s = md_FilterString;
            if (String.IsNullOrWhiteSpace(s))
                return true;
            else
            {
                var srcT = item.GetType();
                foreach (var f in srcT.GetFields())
                {
                    string str = f.GetValue(item) as string;
                    if (String.IsNullOrWhiteSpace(str)) continue;
                    bool b = str.IndexOf(s, StringComparison.OrdinalIgnoreCase) >= 0;
                    if (b) return true;
                }
                foreach (var f in srcT.GetProperties())
                {
                    string str = f.GetValue(item, null) as string;
                    if (String.IsNullOrWhiteSpace(str)) continue;
                    bool b = str.IndexOf(s, StringComparison.OrdinalIgnoreCase) >= 0;
                    if (b) return true;
                }

                return false;
            }
        }

更新: 全文: 代码部分:

namespace WpfApplication2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainWindow_ModelView();
        }
    }

    public class MainWindow_ModelView : NotifyBase
    {
        private string _FilterString = String.Empty;

        public ObservableCollection<ItemClass> d_Items { get; set; }
        public ICollectionView md_LogEntriesStoreView { get; private set; }

        public string md_FilterString
        {
            get { return _FilterString; }
            set
            {
                if (_FilterString != value)
                {
                    _FilterString = value;
                    mf_MakeView();
                    OnPropertyChanged("md_FilterString");
                }
            }
        }

        public MainWindow_ModelView()
        {
            d_Items = new ObservableCollection<ItemClass>() { new ItemClass() { d_Text1 = "Item1Text1", d_Text2 = "Item1Text2" }, 
                new ItemClass() { d_Text1 = "Item2Text1", d_Text2 = "Item2Text2" }, 
                new ItemClass() { d_Text1 = "Item3Text1", d_Text2 = "Item3Text2" } };

            md_LogEntriesStoreView = CollectionViewSource.GetDefaultView(d_Items);
        }

        private void mf_MakeView()
        {
            if (d_Items == null) return;
            md_LogEntriesStoreView = CollectionViewSource.GetDefaultView(d_Items);
            md_LogEntriesStoreView.Filter = mf_UserFilter;
            OnPropertyChanged("md_LogEntriesStoreView");
        }
        private bool mf_UserFilter(object item)
        {
            string s = _FilterString;
            if (String.IsNullOrWhiteSpace(s))
                return true;
            else
            {
                var srcT = item.GetType();
                foreach (var f in srcT.GetFields())
                {
                    string str = f.GetValue(item) as string;
                    if (String.IsNullOrWhiteSpace(str)) continue;
                    bool b = str.IndexOf(s, StringComparison.OrdinalIgnoreCase) >= 0;
                    if (b) return true;
                }
                foreach (var f in srcT.GetProperties())
                {
                    string str = f.GetValue(item, null) as string;
                    if (String.IsNullOrWhiteSpace(str)) continue;
                    bool b = str.IndexOf(s, StringComparison.OrdinalIgnoreCase) >= 0;
                    if (b) return true;
                }

                return false;
            }
        }
    }

    public class ItemClass : NotifyBase
    {
        public string d_Text1 { get; set; }
        public string d_Text2 { get; set; }
    }

    public class NotifyBase : INotifyPropertyChanged
    {
        Guid id = Guid.NewGuid();

        [Browsable(false)]
        [System.Xml.Serialization.XmlAttribute("ID")]
        public Guid ID
        {
            get { return id; }
            set
            {
                if (id != value)
                {
                    id = value;
                    OnPropertyChanged("ID");
                }
            }
        }

        [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }

XAML 部分:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBox Height="23"
                 Text="{Binding md_FilterString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                 HorizontalAlignment="Stretch"
                 Name="textBox1"
                 Margin="2"
                 VerticalAlignment="Top"/>
        <DataGrid ItemsSource="{Binding md_LogEntriesStoreView}"
                  AutoGenerateColumns="False"
                  Grid.Row="1"
                  Margin="2"
                  HorizontalAlignment="Stretch"
                  Name="dataGrid1"
                  VerticalAlignment="Stretch">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Path = d_Text1}"
                                Width="Auto"
                                IsReadOnly="True"/>
                <DataGridTextColumn Binding="{Binding Path = d_Text2}"
                                    Width="*"
                                    IsReadOnly="True" />
             </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

结果:

【讨论】:

  • 好的,我已经完成了这个,网格现在没有填充?不确定是过滤器还是?
  • 如何进行列绑定?例如
  • 用数据填充您的可观察集合后(mt 示例中的 d_Items),调用 md_LogEntriesStoreView = CollectionViewSource.GetDefaultView(d_Items);
  • 好的,现在填充列表,但是当我在文本框中输入时仍然没有任何反应
  • 我在 md_FilterString 的设置器上放了一个断点,它没有中断
猜你喜欢
  • 2018-03-18
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 2011-03-06
  • 2015-07-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多