使用GridView获取ListView标题的高度 [英] Get height of header of a ListView with GridView

查看:272
本文介绍了使用GridView获取ListView标题的高度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何通过 GridView 获取 ListView 的标题高度?它甚至有可能吗?



我需要根据 ListView 所以我开始写一个 Converter 。问题是我无法访问实际高度。



Visual Studio的调试器显示 GridView 有一个名为 HeaderRowPresenter 的属性,该属性又具有属性 ActualHeight 。但我无法访问它, HeaderRowPresenter 似乎是受保护或私有的。



所有其他 ColumnHeader * 属性( ColumnHeaderContainerStyle ColumnHeaderTemplate 等)都是 对于所有 Header * 属性在 Columns (除了作为标题内容的 String )。

顺便说一句:我试图解决一个不同的问题和我目前的方法让我这样做,所以也许我采取了错误的方式。

解决方案

好的,我找到了解决方案,但我不是很自豪,因为它使用反射:

我写了 Converter 一个 View 和一个 ListView 作为值和参数,并返回高度t

  public class HeightSyncConverter:IValueConverter 
{
public object Convert(object value ,类型targetType,对象参数,CultureInfo culture)
{
GridView gvLocal = value作为GridView;
ListView lvOther =参数为ListView;

if(gvLocal == null || lvOther == null)
{
return 0;
}
GridView gvOther =(GridView)lvOther.View;
try
{
//获取非公共HeaderRowPresenter属性
GridViewHeaderRowPresenter hrpLocal =(GridViewHeaderRowPresenter)gvLocal.GetType()。GetProperty(HeaderRowPresenter,BindingFlags.NonPublic | BindingFlags .Instance).GetValue(gvLocal);
GridViewHeaderRowPresenter hrpOther =(GridViewHeaderRowPresenter)gvOther.GetType()。GetProperty(HeaderRowPresenter,BindingFlags.NonPublic | BindingFlags.Instance).GetValue(gvOther);

if(hrpLocal == null || hrpOther == null)
{
return 0;
}

//只有在其他ListView的标题高于本地
的情况下才有效if(hrpLocal.ActualHeight> hrpOther.ActualHeight)
{
返回0;
}
return hrpOther.ActualHeight - hrpLocal.ActualHeight;
}
catch(TargetInvocationException){}

return 0;


公共对象ConvertBack(对象值,类型targetType,对象参数,CultureInfo culture)
{
return null;
}
}

然后我用它来定义 Grid.Row

 < UserControl x:Class =GUI。 ListViewLayout
xmlns =http://schemas.microsoft.com/winfx/2006/xaml/presentation
xmlns:x =http://schemas.microsoft.com/winfx/2006/ xaml
xmlns:mc =http://schemas.openxmlformats.org/markup-compatibility/2006
xmlns:d =http://schemas.microsoft.com/expression/blend/ 2008
xmlns:local =clr-namespace:GUI
xmlns:conv =clr-namespace:GUI.Converter
mc:Ignorable =dd:DesignHeight = 300d:DesignWidth =300
Loaded =Window_Loaded>
< UserControl.Resources>
< Style x:Key =verticalGridViewColumnHeaderTargetType =GridViewColumnHeader>
< Setter Property =ContentTemplate>
< Setter.Value>
< DataTemplate>
< TextBlock Text ={Binding}FontWeight =Bold
VerticalAlignment =CenterTextAlignment =CenterHorizo​​ntalAlignment =Center>
< TextBlock.LayoutTransform>
< RotateTransform Angle =270/>
< /TextBlock.LayoutTransform>
< / TextBlock>
< / DataTemplate>
< / Setter>
< / style>
< conv:HeightSyncConverter x:Key =myConverter/>
< /UserControl.Resources>
< Grid x:Name =grid>
< Grid.ColumnDefinitions>
< ColumnDefinition Width =150/>
< ColumnDefinition Width =150/>
< /Grid.ColumnDefinitions>
< Grid.RowDefinitions>
< RowDefinition Height =Auto/>
< RowDefinition x:Name =fillerRowHeight ={Binding View,ElementName = listView1,Converter = {StaticResource myConverter},ConverterParameter = {x:Reference listView2}}/>
< RowDefinition Height =*/>
< /Grid.RowDefinitions>
< Button x:Name =someControlGrid.RowSpan =2>占位符< / Button>
< ListView x:Name =listView1Grid.Row =2>
< ListView.View>
< GridView>
< GridViewColumn Header =Header 1Width =60/>
< GridViewColumn Header =Header 2Width =60/>
< / GridView>
< /ListView.View>
< / ListView>
< ListView x:Name =listView2Grid.Row =1Grid.Column =1Grid.RowSpan =2>
< ListView.View>
< GridView>
< GridViewColumn Header =Long Header 1
HeaderContainerStyle ={StaticResource verticalGridViewColumnHeader}Width =Auto/>
< GridViewColumn Header =Long Header 2
HeaderContainerStyle ={StaticResource verticalGridViewColumnHeader}Width =Auto/>
< / GridView>
< /ListView.View>
< / ListView>

< / Grid>
< / UserControl>

问题是转换器在 ListView s和它们的头文件被初始化了,所以我重新评估了代码隐藏中的 Binding



<$ p $用户控件
{
public ListViewLayout()
{
InitializeComponent();


private void Window_Loaded(object sender,RoutedEventArgs e)
{
BindingExpression binding = fillerRow.GetBindingExpression(RowDefinition.HeightProperty);
binding.UpdateTarget();
}
}

总而言之,我不认为这是值得付出努力,最好的方法是自己定义标题的高度,而不是检索自动计算的 ActualHeight


How can I get the height of the header of a ListView with a GridView? Is it even possible?

I need to set the height of one control based on the height of the header of a ListView so I started writing a Converter. The problem is that I can't access the actual height.

The debugger of Visual Studio shows me that GridView has a property called HeaderRowPresenter, which in turn has a property ActualHeight. But I can't access it, HeaderRowPresenter seems to be protected or private.

All other ColumnHeader* properties (ColumnHeaderContainerStyle, ColumnHeaderTemplate, etc.) are null on this object, same for all Header* properties on the Columns (except for the String that is the content of the header).

Btw: I'm trying to solve a different problem and my current approach let me to this, so maybe I'm taking this on the wrong way.

解决方案

Okay, I've found a solution but I'm not very proud of it, because it uses reflection:

I wrote a Converter that takes a View and a ListView as value and parameter and returns the height difference of the headers:

public class HeightSyncConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        GridView gvLocal = value as GridView;
        ListView lvOther = parameter as ListView;

        if( gvLocal == null || lvOther == null)
        {
            return 0;
        }
        GridView gvOther = (GridView)lvOther.View;
        try
        {
            // get the non-public HeaderRowPresenter property
            GridViewHeaderRowPresenter hrpLocal = (GridViewHeaderRowPresenter)gvLocal.GetType().GetProperty("HeaderRowPresenter", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(gvLocal);
            GridViewHeaderRowPresenter hrpOther = (GridViewHeaderRowPresenter)gvOther.GetType().GetProperty("HeaderRowPresenter", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(gvOther);

            if( hrpLocal == null || hrpOther == null )
            {
                return 0;
            }

            // Only works if the other ListView's header is higher than the local one's
            if( hrpLocal.ActualHeight > hrpOther.ActualHeight )
            {
                return 0;
            }
            return hrpOther.ActualHeight - hrpLocal.ActualHeight;
        }
        catch(TargetInvocationException) { }

        return 0;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

I then use it to define the height of a Grid.Row:

<UserControl x:Class="GUI.ListViewLayout"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:GUI"
        xmlns:conv="clr-namespace:GUI.Converter"
        mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"
        Loaded="Window_Loaded">
    <UserControl.Resources>
        <Style x:Key="verticalGridViewColumnHeader" TargetType="GridViewColumnHeader">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <TextBlock Text="{Binding}" FontWeight="Bold"
                        VerticalAlignment="Center" TextAlignment="Center" HorizontalAlignment="Center">
                            <TextBlock.LayoutTransform>
                                <RotateTransform Angle="270" />
                            </TextBlock.LayoutTransform>
                        </TextBlock>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <conv:HeightSyncConverter x:Key="myConverter" />
    </UserControl.Resources>
    <Grid x:Name="grid">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="150" />
            <ColumnDefinition Width="150" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition x:Name="fillerRow" Height="{Binding View, ElementName=listView1, Converter={StaticResource myConverter}, ConverterParameter={x:Reference listView2}}" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Button x:Name="someControl" Grid.RowSpan="2">Placeholder</Button>
        <ListView x:Name="listView1" Grid.Row="2">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Header 1" Width="60"/>
                    <GridViewColumn Header="Header 2" Width="60" />
                </GridView>
            </ListView.View>
        </ListView>
        <ListView x:Name="listView2" Grid.Row="1" Grid.Column="1" Grid.RowSpan="2">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Long Header 1" 
                            HeaderContainerStyle="{StaticResource verticalGridViewColumnHeader}" Width="Auto" />
                    <GridViewColumn Header="Long Header 2"
                            HeaderContainerStyle="{StaticResource verticalGridViewColumnHeader}" Width="Auto" />
                </GridView>
            </ListView.View>
        </ListView>

    </Grid>
</UserControl>

The problem is that the converter is called before the ListViews and their headers are initialized, so I reevaluate the Binding in the code-behind:

public partial class ListViewLayout : UserControl
{
    public ListViewLayout()
    {
        InitializeComponent();
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        BindingExpression binding = fillerRow.GetBindingExpression(RowDefinition.HeightProperty);
        binding.UpdateTarget();
    }
}

All in all, I don't think this is worth the effort and the best way is to define the height of the headers myself instead of retrieving an automatically calculated ActualHeight.

这篇关于使用GridView获取ListView标题的高度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆