好吧,标题不是很具描述性,因为它们没有如何命名我要寻找的东西。我会尽力解释。
在.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中,通过使用DependencyProperty
或INotifyPropertyChanged
支持绑定。这些都不意味着在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
。在上面,我没有费心去解决取消订阅
TextChanged
或Filter
事件的问题。如果要解决该特定问题,则相对简单:您需要从事件中取消订阅旧的处理程序(对于TextChanged
,当然,只有e.OldValue is TextBox
为true时)。当然,要执行此操作,您需要按每个
ListView
对象存储旧的事件处理程序委托实例,例如在字典中,甚至可能只有一个私有附加属性(类似于FilterSource
属性,但对其他代码不可见)。这样,您可以稍后检索委托实例,以从事件中取消对其的订阅。
关于c# - 带有附加属性的疑问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30610148/