Xaml 当网格位于数据模板内时,如何设置网格的可视性?

Xaml 当网格位于数据模板内时,如何设置网格的可视性?,xaml,uwp,datatemplate,uwp-xaml,Xaml,Uwp,Datatemplate,Uwp Xaml,在我们的UWP应用程序中,MyListView的DataTemplate在代码中设置为Page.Resources中的DataTemplateA或DataTemplateB。每个数据模板都包含一个网格(TopGrid),其中包含一个DisplayGrid按钮和另一个网格(DisplayGrid) DisplayGrid包含第二个ListView和一个HideGrid按钮 DisplayGrid按钮应显示DisplayGrid。HideGridButton应折叠DisplayGrid XAML是

在我们的UWP应用程序中,MyListView的DataTemplate在代码中设置为Page.Resources中的DataTemplateA或DataTemplateB。每个数据模板都包含一个网格(TopGrid),其中包含一个DisplayGrid按钮和另一个网格(DisplayGrid)

DisplayGrid包含第二个ListView和一个HideGrid按钮

DisplayGrid按钮应显示DisplayGrid。HideGridButton应折叠DisplayGrid

XAML是

<Page.Resources>
    <DataTemplate x:Key="DataTemplateA">
        <Grid Name="TopGrid">
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <StackPanel Orientation="Horizontal">
                <TextBox/>
                <Button Name="DisplayGridButton" Content="Show" Margin="10,0" Click="DisplayGridButton_Click"/>
            </StackPanel>
            <Grid Name="DisplayGrid" Grid.Row="1" Visibility="Collapsed">
                <StackPanel>
                    <Button Name="HideGridButton" Content="Hide" Click="HideGridButton_Click"/>
                    <ListView Name="SecondListView">
                        <ListView.ItemTemplate>
                            <DataTemplate >

                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </StackPanel>
            </Grid>
        </Grid>
    </DataTemplate>

    <DataTemplate x:Key="DataTemplateB">
        <Grid Name="TopGrid">
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <StackPanel Orientation="Horizontal">
                <TextBox/>
                <Button Name="DisplayGridButton" Content="Show" Margin="10,0" Click="DisplayGridButton_Click"/>
            </StackPanel>
            <Grid Name="DisplayGrid" Grid.Row="1" Visibility="Collapsed">
                <StackPanel>
                    <Button Name="HideGridButton" Content="Hide" Click="HideGridButton_Click"/>
                    <ListView Name="SecondListView">
                        <ListView.ItemTemplate>
                            <DataTemplate >

                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </StackPanel>
            </Grid>
        </Grid>
    </DataTemplate>
</Page.Resources>

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ListView Name="MyListView">

    </ListView>
</Grid>
在代码隐藏中,我可以创建事件处理程序,但无法访问DisplayGrid使其可见或折叠

我通常会这样设置可见性

 private void DisplayGridButton_Click(object sender, RoutedEventArgs e)
    {
        DisplayGrid.Visibility = Visibility.Visible;
    }

 private void HideGridButton_Click(object sender, RoutedEventArgs e)
    {
        DisplayGrid.Visibility = Visibility.Collapsed;
    }

如何从按钮单击事件访问DataTemplate中的DisplayGrid?

由于网格是在模板中定义的,因此必须在运行时将其挖掘出来。(如果您可以从代码隐藏中将其引用为“DisplayGrid”,您将不知道它属于哪个listview项。)

实现如下内容的单击处理程序:

private void DisplayGridButton_Click(object sender, RoutedEventArgs e)
{
    Button button = sender as Button;
    StackPanel stackPanel = button?.Parent as StackPanel;
    Grid grid = stackPanel?.Parent as Grid;
    if (grid != null)
    {
        Grid displayGrid = FindVisualChild<Grid>(grid, "DisplayGrid");
        if (displayGrid != null)
        {
            displayGrid.Visibility = Visibility.Visible;
        }
    }
}

private void HideGridButton_Click(object sender, RoutedEventArgs e)
{
    Button button = sender as Button;
    StackPanel stackPanel = button?.Parent as StackPanel;
    Grid grid = stackPanel?.Parent as Grid;
    if (grid != null)
    {
        grid.Visibility = Visibility.Collapsed;
    }
}
private void DisplayGridButton\u单击(对象发送者,路由目标)
{
按钮按钮=发送器为按钮;
StackPanel StackPanel=按钮?。父级为StackPanel;
网格网格=stackPanel?。父网格;
如果(网格!=null)
{
Grid displayGrid=FindVisualChild(网格,“显示网格”);
if(displayGrid!=null)
{
displayGrid.Visibility=可见性.Visibility;
}
}
}
私有void隐藏按钮单击(对象发送方,RoutedEventArgs e)
{
按钮按钮=发送器为按钮;
StackPanel StackPanel=按钮?。父级为StackPanel;
网格网格=stackPanel?。父网格;
如果(网格!=null)
{
grid.Visibility=Visibility.Collapsed;
}
}
(合理的警告:这段代码找到合适的父级开始的方式有点脆弱;如果模板更改,它可能会崩溃。按名称搜索会更好,但我现在手头没有任何东西。)

以下是在可视树中查找命名子级的帮助器方法:

public static T FindVisualChild<T>(
    DependencyObject parent,
    string name = null)
    where T : DependencyObject
{
    if (parent != null)
    {
        int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < childrenCount; i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(parent, i);
            T candidate = child as T;
            if (candidate != null)
            {
                if (name == null)
                {
                    return candidate;
                }

                FrameworkElement element = candidate as FrameworkElement;
                if (name == element?.Name)
                {
                    return candidate;
                }
            }

            T childOfChild = FindVisualChild<T>(child, name);
            if (childOfChild != null)
            {
                return childOfChild;
            }
        }
    }

    return default(T);
}
public static T FindVisualChild(
DependencyObject父对象,
字符串名称=空)
其中T:DependencyObject
{
如果(父项!=null)
{
int childrenCount=visualtreeheloper.GetChildrenCount(父级);
for(int i=0;i

(此方法也可以仅按类型搜索;只需将
null
作为名称传递即可。)

由于网格是在模板中定义的,因此必须在运行时将其挖掘出来。(如果您可以从代码隐藏中将其引用为“DisplayGrid”,您将不知道它属于哪个listview项。)

实现如下内容的单击处理程序:

private void DisplayGridButton_Click(object sender, RoutedEventArgs e)
{
    Button button = sender as Button;
    StackPanel stackPanel = button?.Parent as StackPanel;
    Grid grid = stackPanel?.Parent as Grid;
    if (grid != null)
    {
        Grid displayGrid = FindVisualChild<Grid>(grid, "DisplayGrid");
        if (displayGrid != null)
        {
            displayGrid.Visibility = Visibility.Visible;
        }
    }
}

private void HideGridButton_Click(object sender, RoutedEventArgs e)
{
    Button button = sender as Button;
    StackPanel stackPanel = button?.Parent as StackPanel;
    Grid grid = stackPanel?.Parent as Grid;
    if (grid != null)
    {
        grid.Visibility = Visibility.Collapsed;
    }
}
private void DisplayGridButton\u单击(对象发送者,路由目标)
{
按钮按钮=发送器为按钮;
StackPanel StackPanel=按钮?。父级为StackPanel;
网格网格=stackPanel?。父网格;
如果(网格!=null)
{
Grid displayGrid=FindVisualChild(网格,“显示网格”);
if(displayGrid!=null)
{
displayGrid.Visibility=可见性.Visibility;
}
}
}
私有void隐藏按钮单击(对象发送方,RoutedEventArgs e)
{
按钮按钮=发送器为按钮;
StackPanel StackPanel=按钮?。父级为StackPanel;
网格网格=stackPanel?。父网格;
如果(网格!=null)
{
grid.Visibility=Visibility.Collapsed;
}
}
(合理的警告:这段代码找到合适的父级开始的方式有点脆弱;如果模板更改,它可能会崩溃。按名称搜索会更好,但我现在手头没有任何东西。)

以下是在可视树中查找命名子级的帮助器方法:

public static T FindVisualChild<T>(
    DependencyObject parent,
    string name = null)
    where T : DependencyObject
{
    if (parent != null)
    {
        int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
        for (int i = 0; i < childrenCount; i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(parent, i);
            T candidate = child as T;
            if (candidate != null)
            {
                if (name == null)
                {
                    return candidate;
                }

                FrameworkElement element = candidate as FrameworkElement;
                if (name == element?.Name)
                {
                    return candidate;
                }
            }

            T childOfChild = FindVisualChild<T>(child, name);
            if (childOfChild != null)
            {
                return childOfChild;
            }
        }
    }

    return default(T);
}
public static T FindVisualChild(
DependencyObject父对象,
字符串名称=空)
其中T:DependencyObject
{
如果(父项!=null)
{
int childrenCount=visualtreeheloper.GetChildrenCount(父级);
for(int i=0;i
(此方法也只能按类型搜索;只需将
null
作为名称传递即可。)