c# - 带有附加属性的疑问

标签 c# wpf xaml

好吧,标题不是很具描述性,因为它们没有如何命名我要寻找的东西。我会尽力解释。

在.xaml文件中,是一个控件(假定为文本框),如果键入“文本”,则不能再次使用该属性。如果我们用手写,编译器将显示错误。古德已经解释了为什么我认为现在更容易了。

现在假设我有两个名称为“ Propiedad_1”和“ Propiedad_2”的(DependencyProperty.RegisterAttached ... ...),如果我已经在使用一个,则另一个不能在同一控件中使用,反之亦然反之亦然?

2)在类型为string的依赖项属性内的另一个问题是,是否有可能检查String是否在某个时候发生了变化(围绕尝试不使用变量然后进行比较),我需要避免花费TexBox并避免使用文本框。 TextChanged事件。

谢谢!

编辑

这就是我现在所拥有的。

public static readonly DependencyProperty FilterSourceProperty =
    DependencyProperty.RegisterAttached("FilterSource", typeof (TextBox), typeof (ListViewExtension),
        new FrameworkPropertyMetadata(null, OnTextBoxTextChanged));

public static TextBox GetFilterSource(DependencyObject dObj)
{
    return (TextBox) dObj.GetValue(FilterSourceProperty);
}

public static void SetFilterSource(DependencyObject dObj, TextBox value)
{
    dObj.SetValue(FilterSourceProperty, value);
}

private static void OnTextBoxTextChanged(DependencyObject dObj, DependencyPropertyChangedEventArgs e)
{
    var listView = dObj as ListView;
    var textBox = e.NewValue as TextBox;

    if ((listView == null) || (textBox == null)) return;

    textBox.TextChanged += delegate(object sender, TextChangedEventArgs tcea)
    {

        var view = CollectionViewSource.GetDefaultView(listView.ItemsSource);
        if (view == null) return;
        view.Filter += item =>
        {
            ...
            ...
            ...
            ...
        };
    };
}


在.XAML中

    <TextBox Name="TxtFilter"
             VerticalAlignment="Center"
             VerticalContentAlignment="Center"
             Text="{Binding Filter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" CharacterCasing="Upper"/>

<ListView Margin="0,5,0,0"
          ItemsSource="{Binding Articles}"
          IsSynchronizedWithCurrentItem="True"
          SelectedItem="{Binding SelectedArticle}"
          tools:ListViewExtension.FilterSource="{Binding ElementName=TxtFilter}">


在ViewModel中

public string Filter
{
    get { return _filter; }
    set
    {
        if (_filter == value) return;

        _filter = value;
        RaisePropertyChanged();
    }
}


我现在需要的是通过字符串更改“ TextBox”的使用。

tools:ListViewExtension.FilterSource="{Binding Filter}"

最佳答案

由于缺乏a good, minimal, complete code example以及英语不佳,您的问题很难理解。后者是可以理解的(尽管您仍然必须尽一切努力确保您尽可能地交流),但是绝对应该解决前者。

如果没有这些改进,我想您的问题(均为…供以后参考,请不要在同一帖子中发布两个不同的问题)总计如下:


  
  我有两个附加属性,我想在XAML编辑器中使它们互斥。这可能吗?
  


不会。您看到的行为仅适用于单个属性。如果您尝试多次设置同一属性,则编辑器会抱怨。但是,这样做很容易,因为要做的只是检查元素中是否已使用该属性。

对于应该互斥的两个不同属性,没有任何可行的方法来修改编辑器或编译器的行为以进行检查。

作为替代方案,考虑将两个互斥值实现为单个属性,其中该属性可以接受给定类型的两个不同子类,并且这些子类分别代表两种互斥属性类型之一。


  
  我可以优化属性更新,以便如果分配的新值实际上与当前值相同,则不会引发“属性更改”事件吗?
  


是否可行取决于代码的实际编写方式。在WPF中,通过使用DependencyPropertyINotifyPropertyChanged支持绑定。这些都不意味着在TextChanged属性的对象中出现Text事件,您说这是您不希望引发的事件。

请注意,通常,如果有效值(强制后)实际未更改,DependencyObject.SetValue()将禁止更改通知。另请注意,在大多数其他情况下,额外的更改通知通常不会是真正的性能问题。

缺少良好的代码示例,因此无法提供有关第二个问题的更多建议。

如果您认为这些答案不能合理或有效地解决您的问题,请改进您的帖子,使其更易于理解。


编辑:

关于第一个问题,根据您提供的代码片段(不完整),我想说最简单的方法是使FilterSource具有类型object而不是TextBox,然后在OnTextBoxTextChanged(),检查新值的类型并适当处理。即如果它是TextBox,请执行您现在正在执行的操作(通常…参见下面的(*)),如果它是string实例,则只需直接配置视图的过滤器,而不是将配置放入事件处理程序中即可。


(*) 注意:

我发现您的OnTextBoxTextChanged()方法至少有两个方面需要改进:


无需仅因为文本已更改而重建Filter事件处理程序。相反,您可以仅在视图上调用Refresh()。因此,在这种方法中,您将为Filter事件实现事件处理程序,以始终检索TextBox.Text属性值以进行过滤。您将订阅一次该事件,然后TextChanged的事件处理程序将仅调用Refresh()

string场景中,您将使用Filter事件处理程序,该事件处理程序仅使用string值进行过滤,而无需处理(当然不存在)TextChanged事件。
更大的问题是您只能订阅TextChanged事件。如果只更改一次FilterSource属性,就永远不会注意到问题,但这是一个问题。如果再次更改属性值,则应在订阅新事件处理程序之前取消订阅旧的事件处理程序。如果您进行了上述更改,而TextChanged事件处理程序仅调用Refresh(),则此bug的影响将大大降低。但这仍然是一个错误。


笔记的结尾。


至于问题的第二部分,我认为没有一个需要解决的问题。目前尚不清楚您是在关注TextBox.Text属性还是FilterSource属性,但是我认为,如果新设置的属性值与旧属性相同,则这两个属性都不应该生成更改通知。

如果您有不同的看法,请提供一个更好的代码示例(最小和完整),以清楚地说明实际发生的问题,并清楚,准确地说明问题的根源:代码的当前行为以及与代码的不同之处你想要它。


考虑到以上所有因素,我认为您的OnTextBoxTextChanged()方法应更像这样:

private static void OnTextBoxTextChanged(DependencyObject dObj, DependencyPropertyChangedEventArgs e)
{
    ListView listView = dObj as ListView;

    if (listView == null) return;

    var view = CollectionViewSource.GetDefaultView(listView.ItemsSource);
    if (view == null) return;

    if (e.NewValue is TextBox)
    {
        TextBox newValue = (TextBox)e.NewValue;

        view.Filter += item =>
        {
            string filterString = newValue.Text;

            // filter based on filterString, etc.
        };

        textBox.TextChanged += delegate(object sender, TextChangedEventArgs tcea)
        {
            view.Refresh();
        };
    }
    else if (e.NewValue is string)
    {
        string filterString = (string)e.NewValue;

        view.Filter += item =>
        {
            // filter based on filterString, etc.
        };
    }
    else return;
}


为此,您当然必须将附加属性的类型从TextBox更改为object

在上面,我没有费心去解决取消订阅TextChangedFilter事件的问题。如果要解决该特定问题,则相对简单:您需要从事件中取消订阅旧的处理程序(对于TextChanged,当然,只有e.OldValue is TextBox为true时)。

当然,要执行此操作,您需要按每个ListView对象存储旧的事件处理程序委托实例,例如在字典中,甚至可能只有一个私有附加属性(类似于FilterSource属性,但对其他代码不可见)。这样,您可以稍后检索委托实例,以从事件中取消对其的订阅。

关于c# - 带有附加属性的疑问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30610148/

相关文章:

c# - 列表框的多数据触发条件来检查是否选择了某个项目

xaml - Blend For Visual Studio 2019 中缺少“资源”选项卡

wpf - 在没有 LocBAML 的情况下本地化 WPF 应用程序的最佳方法是什么?

c# - 在 IIS7 中不起作用的 HttpModule

c# - 有没有办法调整其内容的边框大小? (Winnrt Xaml)

c# - ListView Final Column Autosize 创建滚动条

c# - WPF Material Design 按钮悬停

wpf - 使用 Windows 窗体主机在 WPF 中嵌入 SWF 文件?

c# - MvvmCross 4 和 WPF SQLite 插件

c# - 如何对字符串进行拼写检查?