2

我有自己的 VirtualizingWrapPanel,它派生了 VirtualizingPanel 和 IScrollInfo。

下面是如何在 xaml 中使用它的示例:

<ListBox x:Name="StationsListView"
             DataContext="{StaticResource ViewModelKey}"                 
             ItemsSource="{Binding Stations}">
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <common:VirtualizingWrapPanel IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Button Style="{DynamicResource DestinationButtonStyle}">
                    <TextBlock Text="{Binding FullName}"
                               Style="{DynamicResource DestinationStationTextBlockStyle}"
                               TextTrimming="CharacterEllipsis" />
                </Button>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

如果我通过 x:Name="vwp" 为 VirtualizingWrapPanel 命名,那么我可以通过代码隐藏文件中的名称来引用面板,我的意思是,IntelliSense 提供引用面板。但是编译失败。编译器抱怨它无法解析我在 xaml 中给面板的名称。

我通过在 ContendRendered 事件内的对象图中搜索面板解决了这个问题。但这似乎是一个肮脏的黑客。

如何通过使用 Name 属性(以某种方式)克服这个问题?

4

1 回答 1

3

WPF 中的模板与常规 XAML 对象树不同。当您<Window/>在 XAML 中说时,它的意思是“创建Window类的实例”。当您说它的意思是“创建一个知道如何创建窗口<DataTemplate><Window/></DataTemplate>的类的实例”时(也不例外)。从这个意义上说,您的实例仅在模板对象树被实例化后才开始存在 - 但这可能会发生多次!如果它被绑定到您的代码隐藏中的一个实例字段,那么它的哪个实例应该分配给它?DataTemplateItemsPanelTemplateVirtualizingWrapPanel

更一般地说,模板定义了一个名称范围。名称范围内的名称必须是唯一的,并且使用 FrameworkElement.FindName() 进行查找仅适用于已在其中实例化相应 FrameworkElement 的名称范围。一个模板可以被实例化多次,每个实例化定义一个单独的名称范围,您可以在其中查找命名对象。

在对象树中搜索是处理这种情况的一种很好的通用方法。另一种方法是向面板添加行为(即在其 PropertyChanged 处理程序中实现必要逻辑的附加属性)。然后每次执行此模板时都会执行附加的属性逻辑。

于 2013-09-06T05:22:23.293 回答