如何向自定义附加 属性 提供元素集合?
How do I provide a collection of elements to a custom attached property?
我在网上找到了一些例子,在这里找到了一些问题和答案,但我就是无法让它工作。我需要一个可以接受一个或多个目标元素的自定义附加 属性。例如...
<ListView>
<dd:MyDragDrop.DropBorders>
<Binding ElementName="brdOne"/>
<Binding ElementName="brdTwo"/>
<Binding ElementName="brdThree"/>
</dd:MyDragDrop.DropBorders>
</ListView>
我也尝试过使用 MultiBinding,但没有成功。
<ListView>
<dd:MyDragDrop.DropBorders>
<MultiBinding Converter="{StaticResource multi}">
<Binding ElementName="brdOne"/>
<Binding ElementName="brdTwo"/>
<Binding ElementName="brdThree"/>
</MultiBinding>
</dd:MyDragDrop.DropBorders>
</ListView>
稍后有时间我会详细说明,但与此同时.. 有 'correct' 方法吗?感觉应该比我做的简单!
仅供参考,这是我正在玩的附件 属性。现在完全是一个实验,所以根本没有润色,主要是尝试不同在线解决方案的不同解决方案的结果。
public class BorderCollection : List<Border>
{
}
public static readonly DependencyProperty DropBordersProperty = DependencyProperty.RegisterAttached("DropBorders", typeof(BorderCollection), typeof(MyDragDrop));
public static BorderCollection GetDropBorders(ListView listView)
{
var collection = (BorderCollection)listView.GetValue(DropBordersProperty);
if (collection == null)
{
collection = new BorderCollection();
listView.SetValue(DropBordersProperty, collection);
}
return collection;
}
public static void SetDropBorders(ListView listView, BorderCollection borders)
{
listView.SetValue(DropBordersProperty, borders);
foreach (Border border in borders)
{
border.Background = new SolidColorBrush(Colors.Green);
}
}
谢谢。
您的 BorderCollection
是 List
个 Border
个元素,但是,您正在尝试使用 Binding
个元素的集合。
<dd:MyDragDrop.DropBorders>
<Binding ElementName="brdOne"/>
<Binding ElementName="brdTwo"/>
<Binding ElementName="brdThree"/>
</dd:MyDragDrop.DropBorders>
记住,Binding
个元素 不是 Border
个元素。您的 DropBorders
集合需要 Border
的列表。像这样:
<dd:MyDragDrop.DropBorders>
<Border ... />
...
</dd:MyDragDrop.DropBorders>
考虑将您的 BorderCollection
改为继承 List<Binding>
。然后,您可以使用您的绑定集合来获取集合中的边框。
您应该能够执行以下操作:
<ListView>
<dd:MyDragDrop.DropBorders>
<Border Style="{StaticResource brdOneStyle}"/>
<Border Style="{StaticResource brdTwoStyle}"/>
<Border Style="{StaticResource brdThreeStyle}"/>
</dd:MyDragDrop.DropBorders>
</ListView>
我不建议您使用绑定指定 DropBorders,因为 Border 是 UIElement,而 UIElement 只能在可视化树中出现一次。如果您有多个列表视图使用相同的 Border 元素实例,则可能会出现运行时错误。如果您想重复使用边框,请改用样式。
我设法使用这样的 IMultiValueConverter
让它工作:
public class BorderCollectionConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var borderCollection = new BorderCollection();
borderCollection.AddRange(values.OfType<Border>());
return borderCollection;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
并在 XAML 中使用它,就像在您的示例中一样:
<Border Height="20" Name="border1" Background="Blue" />
<Border Height="20" Name="border2" Background="Green" />
<Border Height="20" Name="border3" Background="Yellow" />
<Control>
<dd:MyDragDrop.DropBorders>
<MultiBinding Converter="{StaticResource borderCollectionConverter}">
<Binding ElementName="border1" />
<Binding ElementName="border3" />
</MultiBinding>
</dd:MyDragDrop.DropBorders>
</Control>
主要区别在于我声明 DependencyProperty
的方式,使用问题评论中给出的建议(getter 或 setter 中没有代码,而是使用元数据定义一个 属性 改变的回调):
public static readonly DependencyProperty DropBordersProperty =
DependencyProperty.RegisterAttached("DropBorders", typeof(BorderCollection), typeof(MyDragDrop),
new PropertyMetadata(null, DropBordersChanged));
public static BorderCollection GetDropBorders(DependencyObject listView)
{
return (BorderCollection)listView.GetValue(DropBordersProperty);
}
public static void SetDropBorders(DependencyObject listView, BorderCollection borders)
{
listView.SetValue(DropBordersProperty, borders);
}
public static void DropBordersChanged(object sender, DependencyPropertyChangedEventArgs e)
{
foreach (var border in (BorderCollection)e.NewValue)
border.Background = new SolidColorBrush(Colors.Red);
}
最后的结果...
我在网上找到了一些例子,在这里找到了一些问题和答案,但我就是无法让它工作。我需要一个可以接受一个或多个目标元素的自定义附加 属性。例如...
<ListView>
<dd:MyDragDrop.DropBorders>
<Binding ElementName="brdOne"/>
<Binding ElementName="brdTwo"/>
<Binding ElementName="brdThree"/>
</dd:MyDragDrop.DropBorders>
</ListView>
我也尝试过使用 MultiBinding,但没有成功。
<ListView>
<dd:MyDragDrop.DropBorders>
<MultiBinding Converter="{StaticResource multi}">
<Binding ElementName="brdOne"/>
<Binding ElementName="brdTwo"/>
<Binding ElementName="brdThree"/>
</MultiBinding>
</dd:MyDragDrop.DropBorders>
</ListView>
稍后有时间我会详细说明,但与此同时.. 有 'correct' 方法吗?感觉应该比我做的简单!
仅供参考,这是我正在玩的附件 属性。现在完全是一个实验,所以根本没有润色,主要是尝试不同在线解决方案的不同解决方案的结果。
public class BorderCollection : List<Border>
{
}
public static readonly DependencyProperty DropBordersProperty = DependencyProperty.RegisterAttached("DropBorders", typeof(BorderCollection), typeof(MyDragDrop));
public static BorderCollection GetDropBorders(ListView listView)
{
var collection = (BorderCollection)listView.GetValue(DropBordersProperty);
if (collection == null)
{
collection = new BorderCollection();
listView.SetValue(DropBordersProperty, collection);
}
return collection;
}
public static void SetDropBorders(ListView listView, BorderCollection borders)
{
listView.SetValue(DropBordersProperty, borders);
foreach (Border border in borders)
{
border.Background = new SolidColorBrush(Colors.Green);
}
}
谢谢。
您的 BorderCollection
是 List
个 Border
个元素,但是,您正在尝试使用 Binding
个元素的集合。
<dd:MyDragDrop.DropBorders>
<Binding ElementName="brdOne"/>
<Binding ElementName="brdTwo"/>
<Binding ElementName="brdThree"/>
</dd:MyDragDrop.DropBorders>
记住,Binding
个元素 不是 Border
个元素。您的 DropBorders
集合需要 Border
的列表。像这样:
<dd:MyDragDrop.DropBorders>
<Border ... />
...
</dd:MyDragDrop.DropBorders>
考虑将您的 BorderCollection
改为继承 List<Binding>
。然后,您可以使用您的绑定集合来获取集合中的边框。
您应该能够执行以下操作:
<ListView>
<dd:MyDragDrop.DropBorders>
<Border Style="{StaticResource brdOneStyle}"/>
<Border Style="{StaticResource brdTwoStyle}"/>
<Border Style="{StaticResource brdThreeStyle}"/>
</dd:MyDragDrop.DropBorders>
</ListView>
我不建议您使用绑定指定 DropBorders,因为 Border 是 UIElement,而 UIElement 只能在可视化树中出现一次。如果您有多个列表视图使用相同的 Border 元素实例,则可能会出现运行时错误。如果您想重复使用边框,请改用样式。
我设法使用这样的 IMultiValueConverter
让它工作:
public class BorderCollectionConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var borderCollection = new BorderCollection();
borderCollection.AddRange(values.OfType<Border>());
return borderCollection;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
并在 XAML 中使用它,就像在您的示例中一样:
<Border Height="20" Name="border1" Background="Blue" />
<Border Height="20" Name="border2" Background="Green" />
<Border Height="20" Name="border3" Background="Yellow" />
<Control>
<dd:MyDragDrop.DropBorders>
<MultiBinding Converter="{StaticResource borderCollectionConverter}">
<Binding ElementName="border1" />
<Binding ElementName="border3" />
</MultiBinding>
</dd:MyDragDrop.DropBorders>
</Control>
主要区别在于我声明 DependencyProperty
的方式,使用问题评论中给出的建议(getter 或 setter 中没有代码,而是使用元数据定义一个 属性 改变的回调):
public static readonly DependencyProperty DropBordersProperty =
DependencyProperty.RegisterAttached("DropBorders", typeof(BorderCollection), typeof(MyDragDrop),
new PropertyMetadata(null, DropBordersChanged));
public static BorderCollection GetDropBorders(DependencyObject listView)
{
return (BorderCollection)listView.GetValue(DropBordersProperty);
}
public static void SetDropBorders(DependencyObject listView, BorderCollection borders)
{
listView.SetValue(DropBordersProperty, borders);
}
public static void DropBordersChanged(object sender, DependencyPropertyChangedEventArgs e)
{
foreach (var border in (BorderCollection)e.NewValue)
border.Background = new SolidColorBrush(Colors.Red);
}
最后的结果...