Wpf 模板部件不能作为可视子项使用。默认情况下,自定义控件可见性为Collpase时

Wpf 模板部件不能作为可视子项使用。默认情况下,自定义控件可见性为Collpase时,wpf,xaml,custom-controls,dependency-properties,Wpf,Xaml,Custom Controls,Dependency Properties,我正在使用默认折叠的UserControl内部。按下按钮时,UserControl可见性设置为visible,因此所有内容都应加载到可视化树中。如果visibility设置为Visible,则按以下顺序调用存储库控件 1) 静态多选组合框() 2) 应用程序模板()上的公共重写无效 3) 依赖属性回调 当事件按此顺序排列时。一切都按预期进行 但当“可见性”默认设置为“折叠”时。在应用程序模板之前调用Dependency属性,这是可以理解的。问题在于回调后加载所有属性并绑定所有必需的事件 priv

我正在使用默认折叠的UserControl内部。按下按钮时,UserControl可见性设置为visible,因此所有内容都应加载到可视化树中。如果visibility设置为Visible,则按以下顺序调用存储库控件

1) 静态多选组合框()

2) 应用程序模板()上的公共重写无效

3) 依赖属性回调

当事件按此顺序排列时。一切都按预期进行

但当“可见性”默认设置为“折叠”时。在应用程序模板之前调用Dependency属性,这是可以理解的。问题在于回调后加载所有属性并绑定所有必需的事件

private static void ItemsPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
    LoadComponents(dependencyObject, dependencyPropertyChangedEventArgs);
}

private static void LoadComponents(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
    var control = dependencyObject as MultiSelectComboBox;

    if (control?.MultiSelectComboBoxGrid != null && control?.ItemsSource != null)
    {
        control.ItemsCollectionViewSource = new CollectionViewSource
        {
            Source = control.ItemsSource
        };

        if (dependencyPropertyChangedEventArgs.NewValue is IList newItems && newItems.Count > 0)
        {
            control.UpdateSelectedItemsContainer(newItems);
        }

        if (control.SelectedItemsControl == null)
        {
            control.SelectedItemsControl = VisualTreeService.FindVisualChild<ItemsControl>(control.MultiSelectComboBoxGrid, PART_MultiSelectComboBox_SelectedItemsPanel_ItemsControl);
        }



        if (control.DropdownListBox == null)
        {
            if (control.DropdownMenu == null)
            {
                control.DropdownMenu = VisualTreeService.FindVisualChild<Popup>(control.MultiSelectComboBoxGrid, PART_MultiSelectComboBox_Dropdown);
            }

            if (control.DropdownMenu != null)
            {
                control.DetachedFilterPanel = VisualTreeService.FindVisualChild<StackPanel>(control.DropdownMenu.Child, PART_MultiSelectComboBox_Detached_FilterPanel);
                if (control.DetachedFilterPanel != null)
                {
                    control.DetachedFilterTextBox = VisualTreeService.FindVisualChild<TextBox>(control.DetachedFilterPanel, PART_MultiSelectComboBox_Detached_Filter_TextBox);
                    control.DetachedFilterAutoCompleteTextBox = VisualTreeService.FindVisualChild<TextBox>(control.DetachedFilterPanel, PART_MultiSelectComboBox_Detached_Filter_AutoComplete_TextBox);
                }
                control.DropdownListBox = VisualTreeService.FindVisualChild<ListBox>(control.DropdownMenu.Child, PART_MultiSelectComboBox_Dropdown_ListBox);
            }
        }
    }
}
私有静态无效项PropertyChangedCallback(DependencyObject DependencyObject,DependencyPropertyChangedEventArgs DependencyPropertyChangedEventArgs)
{
LoadComponents(dependencyObject、dependencyPropertyChangedEventArgs);
}
专用静态void加载组件(DependencyObject DependencyObject、DependencyPropertyChangedEventArgs DependencyPropertyChangedEventArgs)
{
var control=作为MultiSelectComboBox的dependencyObject;
if(control?.multiselectComboxGrid!=null和&control?.ItemsSource!=null)
{
control.ItemsCollectionViewSource=新集合ViewSource
{
Source=control.ItemsSource
};
如果(dependencyPropertyChangedEventArgs.NewValue为IList newItems&&newItems.Count>0)
{
control.updateselecteditemscocontainer(newItems);
}
if(control.SelectedItemsControl==null)
{
control.SelectedItemsControl=VisualTreeseService.FindVisualChild(control.multiselectComboxGrid,PART\u multiselectComboxBox\u SelectedItemsPanel\u ItemsControl);
}
if(control.DropdownListBox==null)
{
如果(control.DropdownMenu==null)
{
control.DropdownMenu=VisualTreeService.FindVisualChild(control.MultiselectComboxGrid,PART_MultiselectComboxBox_下拉菜单);
}
如果(control.DropdownMenu!=null)
{
control.DetachedFilterPanel=VisualTreeService.FindVisualChild(control.DropdownMenu.Child,PART\u MultiSelectComboBox\u Detached\u FilterPanel);
if(control.DetachedFilterPanel!=null)
{
control.DetachedFilterTextBox=VisualTreeService.FindVisualChild(control.DetachedFilterPanel,PART\u MultiSelectComboBox\u Distached\u Filter\u TextBox);
control.DetachedFilterAutoCompleteTextBox=VisualTreeService.FindVisualChild(control.DetachedFilterPanel,PART\u MultiSelectComboBox\u Detached\u Filter\u AutoComplete\u TextBox);
}
control.DropdownListBox=VisualTreeService.FindVisualChild(control.dropdownlmenu.Child,PART\u MultiSelectComboBox\u Dropdown\u ListBox);
}
}
}
}
在我的场景中,这是在OnApplyTemplate之前调用的,所以我创建了一个名为LoadComponent function的函数,并从OnApplyTemplate调用了它。每件事都很好,除了下面的总是给空值,当我检查视觉树时,它甚至不在那里

if (control.SelectedItemsControl == null)
{
    control.SelectedItemsControl = VisualTreeService.FindVisualChild<ItemsControl>(control.MultiSelectComboBoxGrid, PART_MultiSelectComboBox_SelectedItemsPanel_ItemsControl);
}
if(control.SelectedItemsControl==null)
{
control.SelectedItemsControl=VisualTreeseService.FindVisualChild(control.multiselectComboxGrid,PART\u multiselectComboxBox\u SelectedItemsPanel\u ItemsControl);
}
我无法理解这背后的原因。这是这个部分的Xaml

<DataTemplate x:Key="MultiSelectComboBox.SelectedItemsPanel.Template">
    <Border Background="White" BorderBrush="{StaticResource MultiSelectComboBox.SelectedItemsPanel.Border}" BorderThickness="1">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="20"/>
            </Grid.ColumnDefinitions>

            <Border Grid.Column="0" Margin="1" Background="White" BorderThickness="0">
                <sdl:ContentItemsControl x:Name="PART_MultiSelectComboBox_SelectedItemsPanel_ItemsControl"                            
                        ItemContainerStyle="{StaticResource MultiSelectComboBox.SelectedItems.ItemContainer.Style}"                           
                        Style="{StaticResource MultiSelectComboBox.SelectedItemsPanel.WrapableItemsSource.Style}">
                    <sdl:ContentItemsControl.Resources>
                        <DataTemplate x:Key="MultiSelectComboBox.SelectedItems.ItemTemplate">
                            <TextBlock Text="{Binding}" Style="{DynamicResource MultiSelectComboBox.DefaultTextBlock.Style}" Margin="2,0" />
                        </DataTemplate>
                        <DataTemplate x:Key="MultiSelectComboBox.SelectedItems.Searchable.ItemTemplate">
                            <StackPanel Orientation="Horizontal">
                                <TextBox x:Name="PART_MultiSelectComboBox_SelectedItemsPanel_Filter_TextBox" IsEnabled="{Binding IsEditMode, RelativeSource={RelativeSource TemplatedParent}}" 
                                     Focusable="True" IsTabStop="False" Margin="0" ForceCursor="True" BorderThickness="0" BorderBrush="Transparent" Padding="1" TextWrapping="NoWrap"/>
                                <TextBox x:Name="PART_MultiSelectComboBox_SelectedItemsPanel_Filter_AutoComplete_TextBox" IsReadOnly="True"
                                     Focusable="False" IsTabStop="False" Margin="-2,0,0,0" BorderThickness="0" BorderBrush="Transparent" Padding="-3,1,0,1" TextWrapping="NoWrap"/>
                            </StackPanel>
                        </DataTemplate>
                    </sdl:ContentItemsControl.Resources>
                </sdl:ContentItemsControl>
            </Border>

            <Button x:Name="PART_MultiSelectComboBox_Dropdown_Button" Grid.Column="1" Style="{StaticResource MultiSelectComboBox.DropDown.Button.Style}" >
                <ContentControl>
                    <ContentControl.Style>
                        <Style TargetType="ContentControl">
                            <Setter Property="IsTabStop" Value="False"/>
                            <Setter Property="ContentTemplate" Value="{StaticResource MultiSelectComboBox.SelectedItemsPanel.Readonly.Glyph.Template}"/>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type sdl:MultiSelectComboBox}}, Path=IsEditMode}" Value="True">
                                    <Setter Property="ContentTemplate" Value="{StaticResource MultiSelectComboBox.SelectedItemsPanel.EditMode.Glyph.Template}"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </ContentControl.Style>
                </ContentControl>

            </Button>
        </Grid>
    </Border>
</DataTemplate>

<Style x:Key="MultiSelectComboBox.Custom.Style" TargetType="{x:Type sdl:MultiSelectComboBox}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type sdl:MultiSelectComboBox}">

                <Grid x:Name="PART_MultiSelectComboBox" MaxHeight="{TemplateBinding ActualHeight}" MaxWidth="{TemplateBinding ActualWidth}" Style="{StaticResource MultiSelectComboBox.Style}">
                    <ToggleButton KeyboardNavigation.TabNavigation="None" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" IsTabStop="False">
                        <ToggleButton.Template>
                            <ControlTemplate TargetType="ToggleButton">
                                <ContentControl ContentTemplate="{StaticResource MultiSelectComboBox.SelectedItemsPanel.Template}"/>
                            </ControlTemplate>
                        </ToggleButton.Template>
                    </ToggleButton>

                    <Popup x:Name="PART_MultiSelectComboBox_Dropdown" Margin="2" Grid.ColumnSpan="2" MaxHeight="{Binding Path=MaxDropDownHeight, RelativeSource={RelativeSource TemplatedParent} }" PlacementTarget="{Binding ElementName=PART_MultiSelectComboBox}" IsOpen="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" MaxWidth="{TemplateBinding ActualWidth}" Placement="Bottom" AllowsTransparency="True" PopupAnimation="Slide">
                        <themes:SystemDropShadowChrome x:Name="shadow" Color="Transparent" MinWidth="{Binding ActualWidth, ElementName=PART_MultiSelectComboBox}">
                            <Border x:Name="dropDownBorder" Margin="0,1,0,0" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="0" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="*"/>
                                    </Grid.RowDefinitions>
                                    <Grid Grid.Row="0" Visibility="{Binding DetachAutoCompleteFilterBox, RelativeSource={RelativeSource TemplatedParent},Converter={StaticResource BoolToVis},FallbackValue=Collpased}">
                                        <Border BorderBrush="LightBlue" BorderThickness="1">
                                            <Border.Effect>
                                                <DropShadowEffect ShadowDepth="0" Color="LightBlue" Opacity="1" BlurRadius="10"/>
                                            </Border.Effect>
                                        </Border>
                                        <Border Padding="2">
                                            <StackPanel x:Name="PART_MultiSelectComboBox_Detached_FilterPanel"  Orientation="Horizontal" Height="30">
                                                <TextBox x:Name="PART_MultiSelectComboBox_Detached_Filter_TextBox" Margin="1,0,0,0" IsEnabled="{Binding IsEditMode, RelativeSource={RelativeSource TemplatedParent}}" 
                                     Focusable="True" IsTabStop="False"  ForceCursor="True" BorderThickness="0" BorderBrush="Transparent" Padding="1" TextWrapping="NoWrap"/>
                                                <TextBox x:Name="PART_MultiSelectComboBox_Detached_Filter_AutoComplete_TextBox" IsReadOnly="True"
                                     Focusable="False" IsTabStop="False" Margin="-2,0,0,0" BorderThickness="0" BorderBrush="Transparent" Padding="-3,1,0,1" TextWrapping="NoWrap"/>
                                            </StackPanel>
                                        </Border>
                                    </Grid>
                                    <Grid x:Name="grid" Grid.Row="1" RenderOptions.ClearTypeHint="Enabled" 
                                          Visibility="{Binding Path=IsLoadingSuggestions, 
                                          RelativeSource={RelativeSource Mode=TemplatedParent}, 
                                          Converter={StaticResource ResourceKey=InvBoolToVis}}"
                                          >
                                        <Grid  Visibility="{Binding Path=IsLoadingSuggestions, 
                                               RelativeSource={RelativeSource Mode=TemplatedParent}, 
                                               Converter={StaticResource ResourceKey=InvBoolToVis}}">
                                            <Canvas x:Name="canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
                                                <Rectangle x:Name="opaqueRect" Fill="{Binding Background, ElementName=dropDownBorder}" Height="{Binding ActualHeight, ElementName=dropDownBorder}" Width="{Binding ActualWidth, ElementName=dropDownBorder}"/>
                                            </Canvas>
                                            <sdl:ExtendedListBox x:Name="PART_MultiSelectComboBox_Dropdown_ListBox" Style="{StaticResource MultiSelectComboBox.Dropdown.ListBox.Style}">
                                                <sdl:ExtendedListBox.GroupStyle>
                                                    <GroupStyle HeaderTemplate="{StaticResource MultiSelectComboBox.Dropdown.ListBox.Header.Template}"/>
                                                </sdl:ExtendedListBox.GroupStyle>
                                                <sdl:ExtendedListBox.Resources>
                                                    <DataTemplate x:Key="MultiSelectComboBox.Dropdown.ListBox.ItemTemplate">
                                                        <TextBlock Text="{Binding}" Style="{StaticResource MultiSelectComboBox.DefaultTextBlock.Style}" Margin="2,2,2,3"/>
                                                    </DataTemplate>
                                                </sdl:ExtendedListBox.Resources>
                                            </sdl:ExtendedListBox>
                                        </Grid>
                                        <ContentPresenter ContentSource="LoadingSuggestionsContent" 
                                                          Visibility="{Binding Path=IsLoadingSuggestions, 
                                                          RelativeSource={RelativeSource Mode=TemplatedParent}, 
                                                          Converter={StaticResource ResourceKey=BoolToVis}}"/>
                                    </Grid>
                                </Grid>
                            </Border>
                        </themes:SystemDropShadowChrome>
                    </Popup>
                </Grid>

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

private static void ItemsPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
    var control = dependencyObject as MultiSelectComboBox;
    if(control != null && control.MultiSelectComboBoxGrid == null)
    {
        control.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, (Action)(() => LoadComponents(dependencyObject, dependencyPropertyChangedEventArgs)));
        return;
    }
    LoadComponents(dependencyObject, dependencyPropertyChangedEventArgs);
}