.net 附加属性无法按预期工作
我想创建一个只显示符合控件边界的项的控件。为此,我创建了自己的面板,该面板继承自StackPanel并覆盖ArrangeOverride过程。在那里,我让默认的StackPanel进行排列,然后我检测到不符合面板边界的项目并将其隐藏。这很有魅力 现在我想知道一个项目是否因为不适合我的面板边界而被隐藏。为此,我创建了一个附加属性,在隐藏该项时将其设置为True。我将视图模型中的一个属性绑定到此附加属性。但我从未得到信息,不管物品是否被隐藏 为了简单起见,我创建了一个小示例项目,它显示了我的问题,但没有所有的开销 我希望你们中的一个能弄明白为什么我没有得到我所渴望的信息 这是我的面板。在每一个第二项中,字符串类型的附加属性测试都设置为Filled,否则它的默认值为空.net 附加属性无法按预期工作,.net,wpf,.net,Wpf,我想创建一个只显示符合控件边界的项的控件。为此,我创建了自己的面板,该面板继承自StackPanel并覆盖ArrangeOverride过程。在那里,我让默认的StackPanel进行排列,然后我检测到不符合面板边界的项目并将其隐藏。这很有魅力 现在我想知道一个项目是否因为不适合我的面板边界而被隐藏。为此,我创建了一个附加属性,在隐藏该项时将其设置为True。我将视图模型中的一个属性绑定到此附加属性。但我从未得到信息,不管物品是否被隐藏 为了简单起见,我创建了一个小示例项目,它显示了我的问题,但
Public Class StackPanelEx
Inherits StackPanel
Public Shared TestProperty As DependencyProperty = DependencyProperty.RegisterAttached("Test", GetType(String), GetType(StackPanelEx), New FrameworkPropertyMetadata("Empty"))
Public Shared Function GetTest(ByVal d As DependencyObject) As String
Return d.GetValue(StackPanelEx.TestProperty)
End Function
Public Shared Sub SetTest(ByVal d As DependencyObject, ByVal value As String)
d.SetValue(StackPanelEx.TestProperty, value)
End Sub
Protected Overrides Function ArrangeOverride(finalSize As Size) As Size
Dim result As Size
Dim index As Integer
result = MyBase.ArrangeOverride(finalSize)
For Each child As UIElement In MyBase.InternalChildren
index += 1
If (index Mod 2) = 0 Then
StackPanelEx.SetTest(child, "Filled")
End If
Next child
Return result
End Function
End Class
这是我的ItemViewModel,简单明了:
Imports System.ComponentModel
Public Class ItemViewModel
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Protected Sub OnPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Private _caption As String
Public Property Caption As String
Get
Return _caption
End Get
Set(value As String)
_caption = value
Me.OnPropertyChanged(NameOf(Me.Caption))
End Set
End Property
End Class
这是我的MainViewModel,包含一组ItemViewModels:
Imports System.Collections.ObjectModel
Imports System.ComponentModel
Public Class MainViewModel
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Protected Sub OnPropertyChanged(propertyName As String)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
End Sub
Private ReadOnly _items As ObservableCollection(Of ItemViewModel)
Public Sub New()
_items = New ObservableCollection(Of ItemViewModel)
_items.Add(New ItemViewModel With {.Caption = "Item 1"})
_items.Add(New ItemViewModel With {.Caption = "Item 2"})
_items.Add(New ItemViewModel With {.Caption = "Item 3"})
_items.Add(New ItemViewModel With {.Caption = "Item 4"})
_items.Add(New ItemViewModel With {.Caption = "Item 5"})
End Sub
Public ReadOnly Property Items As ObservableCollection(Of ItemViewModel)
Get
Return _items
End Get
End Property
End Class
最后是我的主窗口,您可能需要调整本地名称空间:
<Window x:Class="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:WpfApp4"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ItemsControl Grid.Column="0"
ItemsSource="{Binding Items}"
MinWidth="50">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Caption}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl Grid.Column="1"
ItemsSource="{Binding Items}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<local:StackPanelEx Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Caption}" Margin="2" local:StackPanelEx.Test="{Binding Caption, Mode=OneWayToSource}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
所有项目的标题都显示为空,因此“我的附加属性”的默认值有效。但由于在面板的ArrangeOverride中设置了附加属性的值,因此我希望每一秒都显示填充的标题
Snoop告诉我,我的附加属性的值确实在每一个条目中都被填充,所以我的绑定中似乎有问题
我不知道我哪里出错了 ItemTemplate中的按钮不是用作ItemsPanel的StackPanelEx的直接子级,因此按钮上从未设置附加属性 ItemsControl创建ContentPresenter作为项容器元素,该元素将其ContentTemplate属性设置为ItemTemplate 将绑定移动到ItemContainerStyle:
<ItemsControl ...>
...
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="local:StackPanelEx.Test"
Value="{Binding Caption, Mode=OneWayToSource}"/>
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>