【问题标题】:Data Grid Row Header Not Resizing To Contents数据网格行标题未根据内容调整大小
【发布时间】:2018-10-10 01:39:11
【问题描述】:

我正在自定义一个 DataGrid,以便用户可以通过 TextBox 将信息直接输入到标题中。

我遇到的问题是,当文本更改时,行标题没有调整大小以匹配内容的大小:

之前:

之后:

如您所见,一旦文本框的大小缩小以匹配新文本,标题不会缩小以匹配文本框。

符合Minimal, Complete and Verifiable Example 要求:

<Window
    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:l="clr-namespace:MCVE"
    xmlns:lib="clr-namespace:System;assembly=mscorlib"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    x:Class="MCVE.MainWindow"
    mc:Ignorable="d" Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <x:Array x:Key="Source" Type="{x:Type lib:String}">
            <lib:String>Foo</lib:String>
            <lib:String>Bar</lib:String>
            <lib:String>Baz</lib:String>
        </x:Array>
    </Window.Resources>
    <DataGrid
        AutoGenerateColumns="False"
        ItemsSource="{StaticResource Source}"
        RowHeight="50">
        <DataGrid.RowHeaderStyle>
            <Style TargetType="{x:Type DataGridRowHeader}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <TextBox FontSize="36" HorizontalAlignment="Left" Text="This Is A Test" />
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.RowHeaderStyle>
    </DataGrid>
</Window>

在任何行标题中输入一些内容。然后清除它以重现。

那么我可以做些什么来强制行标题宽度并确保它保持可能的最小宽度(不侵犯实际的行标题内容)?

【问题讨论】:

    标签: c# wpf xaml controltemplate datagridrowheader


    【解决方案1】:

    您可以为TextBox 元素处理SizeChanged 事件并跟踪它们的宽度。试试这个:

    private readonly Dictionary<TextBox, double> _widths = new Dictionary<TextBox, double>();
    private void TextBox_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        TextBox textBox = (TextBox)sender;
        _widths[textBox] = textBox.ActualWidth;
    
        double largestWidth = _widths.Values.Max();
        DataGridRowHeader header = FindParent<DataGridRowHeader>(textBox);
        dg.RowHeaderWidth = double.NaN;
        if (header != null)
            dg.RowHeaderWidth = dg.RowHeaderActualWidth > largestWidth ? largestWidth : double.NaN;
    }
    

    XAML:

    <DataGrid.RowHeaderStyle>
        <Style TargetType="{x:Type DataGridRowHeader}">
            <Setter Property="Width" Value="Auto" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <TextBox FontSize="36" HorizontalAlignment="Left" Text="This Is A Test"
                                               SizeChanged="TextBox_SizeChanged" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGrid.RowHeaderStyle>
    

    【讨论】:

    • 这打破了我试图维护的 MVVM 方法,但它确实有助于实现我的目标谢谢。
    • 为什么这会破坏 MVVM 模式?这只是纯视图逻辑。
    • 您的解决方案将代码直接实现到 XAML 之外的视图类代码(代码隐藏)中,并要求“视图”连接到该代码。我对 MVVM 的理解有些有限,并且可能会出错,但我认为在“代码隐藏”视图中包含代码违背了 MVVM 模式。
    • 您对 MVVM 的假设是错误的。 MVVM 并不是要从其所属的视图中消除与 view 相关的代码。这是关于关注点的分离。处理一些与如何在视图模型中设置 RowHeaderWidth 的宽度相关的逻辑是错误的。这纯粹是与视图相关的,应该在视图或控件中处理。
    • 很公平。感谢您澄清我对该主题的看法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    • 2014-04-29
    • 2021-07-26
    • 2011-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多