簡體   English   中英

WPF:綁定數據網格標題寬度

[英]WPF: Binding Data Grid Header Width

我試圖將一個數據網格的標頭的寬度綁定到另一個數據網格的標頭。

因此,我為父數據網格的每一行添加了一個數據網格。 現在,我嘗試使用“父”標頭的列控制子數據網格的列大小。

因此,在最后一列的標題模板中,我添加了一個僅具有列標題而沒有行的數據網格。 在本專欄的單元模板中,我添加了另一個數據網格,沒有標題,只有數據行。

當我調整headertemplate datagrid列標題的大小時,XAML中有什么方法可以調整celltemplate的datagrid列的大小。

閱讀大量關於SO的答案,以及關於CodeProject等的一些帖子,但是我無法使其工作。 有可能嗎?

XAML

 <Grid>
            <DataGrid x:Name="Test"
                      AutoGenerateColumns="False"
                      CanUserAddRows="False"
                      ItemsSource="{Binding AllAssets}"
                      CanUserResizeColumns="True">
                <DataGrid.Resources>               
                    <DataTemplate x:Key="NewKey2">
                        <DataGrid Name="dgC"
                                  AutoGenerateColumns="False"
                                  HeadersVisibility="None"
                                  ItemsSource="{Binding months}"
                                  CanUserResizeColumns="True">
                            <DataGrid.Columns>
                                <DataGridTextColumn x:Name="Col1" Binding="{Binding value}" />
                                <DataGridTextColumn x:Name="Col2" Binding="{Binding MonthName}" />
                            </DataGrid.Columns>
                        </DataGrid>
                    </DataTemplate>
                    <DataTemplate x:Key="NewKey3">
                        <StackPanel>
                            <Label HorizontalAlignment="Center">All Headers</Label>
                            <DataGrid Name="dgH">
                                <DataGrid.Columns>
                                    <DataGridTextColumn Width="{Binding ElementName=Col1, Path=ActualWidth}" Header="Value" />
                                    <DataGridTextColumn Width="{Binding ElementName=Col2, Path=ActualWidth}" Header="Month" />
                                    <!--Error or no result on these attempts
                                    <DataGridTextColumn Header="Month" Width="{Binding Source={x:Reference Col2}, Path=ActualWidth}"/>--><!--
                                    <DataGridTextColumn >
                                        <DataGridTextColumn.Header>
                                            <TextBlock Width="{Binding Source={x:Reference Col1}, Path=ActualWidth}" >Value</TextBlock>
                                        </DataGridTextColumn.Header>
                                    </DataGridTextColumn>
                                    <DataGridTextColumn  Header="Month" />-->
                                </DataGrid.Columns>
                            </DataGrid>
                        </StackPanel>
                    </DataTemplate>
                </DataGrid.Resources>
                <DataGrid.Columns>
                    <DataGridTemplateColumn Header="Id">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Label Content="{Binding id}" />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTemplateColumn Header="Name">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Label Content="{Binding name}" />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTemplateColumn CellTemplate="{StaticResource NewKey2}"
                                            HeaderTemplate="{StaticResource NewKey3}" />
                </DataGrid.Columns>

            </DataGrid>
        </Grid>

C#類數據例如:

namespace WpfApplication1
{
    public class Assets
    {
        public List<Asset> AllAssets { get; set; }

        public Assets()
        {
            AllAssets = new List<Asset>();

            for (int i = 1; i < 3; i++)
            {
                Asset asset = new Asset();

                asset.id = i;
                asset.name = "asset " + i.ToString();

                for (int x = 1; x < 3; x++)
                {
                    MonthsData months = new MonthsData();
                    months.MonthName = "Month " + x.ToString();
                    months.value = x;
                    asset.months.Add(months);
                }

                AllAssets.Add(asset);
            }
        }

    }

    public class Asset
    {
        public int id { get; set; }
        public string name { get; set; }
        public List<MonthsData> months { get; set; }

        public Asset()
        {
            months = new List<MonthsData>();
        }
    }

    public class MonthsData 
    {
        public string MonthName { get; set; }
        public int value { get; set; }
    }
}

在此處輸入圖片說明

假設您可以在ViewModel中定義幾個屬性

public class Assets : MVVM.ViewModel.ViewModelBase
{
    public List<Asset> AllAssets { get; set; }
    private double col1Width;
    private double col2Width;
    public double Col1Width
    {
        get { return col1Width; }
        set { col1Width = value; OnPropertyChanged("Col1Width"); }
    }
    public double Col2Width
    {
        get { return col2Width; }
        set { col2Width = value; OnPropertyChanged("Col2Width"); }
    }

那么您將能夠通過助手從XAML讀取Load事件時的實際寬度

    private void Grid_Loaded(object sender, RoutedEventArgs e)
    {
        var dg = FindVisualChildByName<DataGrid>(Test, "dgC");
        assets.Col1Width = dg.Columns[0].ActualWidth;
        assets.Col2Width = dg.Columns[1].ActualWidth;

    }

並將它們從網格的DataContext設置回XAML綁定

                            <DataGridTextColumn Header="Value" >
                                <DataGridTextColumn.HeaderStyle>
                                    <Style TargetType="DataGridColumnHeader">
                                        <Setter Property="Width" Value="{Binding ElementName=Test, Path=DataContext.Col1Width, UpdateSourceTrigger=PropertyChanged}"/>
                                    </Style>
                                </DataGridTextColumn.HeaderStyle>
                            </DataGridTextColumn>
                            <DataGridTextColumn Header="Month" >
                                <DataGridTextColumn.HeaderStyle>
                                    <Style TargetType="DataGridColumnHeader">
                                        <Setter Property="Width" Value="{Binding ElementName=Test, Path=DataContext.Col2Width, UpdateSourceTrigger=PropertyChanged}"/>
                                    </Style>
                                </DataGridTextColumn.HeaderStyle>
                            </DataGridTextColumn>

回復評論

正如下面的注釋中正確指出的那樣,我們可以避免“僅與ViewModel中的View相關的屬性”,並管理任意(但固定)數目的列,以使dgC和dgH的寬度相同(假設它們具有相同的寬度)列數)鏈接

    private void Grid_Loaded(object sender, RoutedEventArgs e)
    {
        var dgC = FindVisualChildByName<DataGrid>(Test, "dgC");
        var dgH = FindVisualChildByName<DataGrid>(Test, "dgH");
        for (int i = 0; i < dgC.Columns.Count; i++)
        {
            dgH.Columns[i].Width = dgC.Columns[i].ActualWidth;
        }

    }

在這種情況下,不再需要VM綁定

                            <DataGridTextColumn Header="Value" />
                            <DataGridTextColumn Header="Month" />

同時管理列大小調整(如果不需要,請跳過此步驟)

這比較復雜,因此,只有在嚴格要求時才繼續操作。

讓我們更改該實用程序,以便它將返回所有datagrid dgC(每行有一個dgC)

    public static IEnumerable<T> FindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject
    {
        List<T> list = new List<T>();
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
        {
            var child = VisualTreeHelper.GetChild(parent, i);
            string controlName = child.GetValue(Control.NameProperty) as string;
            if (controlName == name)
            {
                list.Add(child as T);
            }
            else
            {
                IEnumerable<T> result = FindVisualChildByName<T>(child, name);
                if (result != null)
                    list.AddRange(result);
            }
        }
        return list;
    }

現在我們將為實際的寬度變化定義一個依賴屬性

    private bool _columnWidthChanging;
    private void ColumnWidthPropertyChanged(object sender, EventArgs e)
    {
        // listen for when the mouse is released
        _columnWidthChanging = true;
        if (sender != null)
            Mouse.AddPreviewMouseUpHandler(this, BaseDataGrid_MouseLeftButtonUp);
    }

    void BaseDataGrid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        if (_columnWidthChanging)
        {
            _columnWidthChanging = false;
            var dgCs = FindVisualChildByName<DataGrid>(Test, "dgC");
            var dgH = FindVisualChildByName<DataGrid>(Test, "dgH").First();
            foreach (var dgC in dgCs)
            {
                for (int i = 0; i < dgC.Columns.Count; i++)
                {

                    var column = dgH.Columns[i];
                    dgC.Columns[i].Width = column.ActualWidth;
                }
            }
        }
    }

    private void Grid_Loaded(object sender, RoutedEventArgs e)
    {
        var dgC = FindVisualChildByName<DataGrid>(Test, "dgC").First();
        var dgH = FindVisualChildByName<DataGrid>(Test, "dgH").First();
        for (int i = 0; i < dgC.Columns.Count; i++)
        {
            var column = dgC.Columns[i];
            dgH.Columns[i].Width = column.ActualWidth;

            PropertyDescriptor pd = DependencyPropertyDescriptor
                         .FromProperty(DataGridColumn.ActualWidthProperty,
                                       typeof(DataGridColumn));

                //Add a listener for this column's width
                pd.AddValueChanged(dgH.Columns[i],
                                   new EventHandler(ColumnWidthPropertyChanged));


        }

您可以使用一個Grid ,並設置SharedSizeGroup財產ColumnDefinition 這將“自動”調整Grid.IsSharedSizeScope定義的列的Grid.IsSharedSizeScope

如果您想了解有關此內置功能的更多信息,可以在Google上進行搜索或查看: https : //wpf.2000things.com/tag/sharedsizegroup/

我采用了您的代碼以使其正常工作。 我取代了DataGrid頁眉/細胞模板,用一Grid為了使用

XAML

<Grid Grid.IsSharedSizeScope="True">
<DataGrid AutoGenerateColumns="False"
            CanUserAddRows="False"
            ItemsSource="{Binding AllAssets}"
            CanUserResizeColumns="True">
    <DataGrid.Resources>
        <DataTemplate x:Key="NewKey2">
            <ItemsControl ItemsSource="{Binding months}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Grid ShowGridLines="True">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition SharedSizeGroup="A" />
                                <ColumnDefinition SharedSizeGroup="B" />
                            </Grid.ColumnDefinitions>
                            <TextBlock Text="{Binding value}"
                                        Margin="5" />
                            <TextBlock Text="{Binding MonthName}"
                                        Margin="5"
                                        Grid.Column="2" />
                        </Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DataTemplate>
        <DataTemplate x:Key="NewKey3">
            <StackPanel>
                <Label HorizontalAlignment="Center">All Headers</Label>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition SharedSizeGroup="A" />
                        <ColumnDefinition SharedSizeGroup="B" />
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="Value"
                                Margin="5" />
                    <TextBlock Text="Month"
                                Margin="5"
                                Grid.Column="1" />
                </Grid>
            </StackPanel>
        </DataTemplate>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Id">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Label Content="{Binding id}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Name"
                                Width="Auto">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Label Content="{Binding name}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn CellTemplate="{StaticResource NewKey2}"
                                HeaderTemplate="{StaticResource NewKey3}" />
    </DataGrid.Columns>
</DataGrid>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM