XAML DataGrid列宽不自动更新

but5z9lq  于 2022-12-07  发布在  其他
关注(0)|答案(5)|浏览(166)
<DataGridTextColumn Binding="{Binding Name}" Width="*"/>
<DataGridTextColumn Binding="{Binding Change}" Width="Auto"/>

Change的值更新时,它的列不会更新以适应新值。因此,该列仍然太小,值被剪切。
有什么想法吗?

u4vypkhs

u4vypkhs1#

当数据变长时,DataGrid将增加列的大小以适应数据,但当数据的长度减小时,它不会自动减小列的大小。在示例中,您将"更改"列右对齐,并将其余空间用于"名称"列。
现在,当"Change"属性增长到足以增加列的宽度时,"Name"列拒绝收缩以适应,因此您必须自己强制刷新。

以下步骤可以帮助您完成此操作(我已提供了一个示例应用程序进行演示):

1)在DataGridTextColumn系结中(除了 * 大小的数据行以外的所有数据行),设定NotifyTargetUpdated = True。
2)在DataGrid上,将行程常式加入至TargetUpdated事件。
3)在TargetUpdated事件行程常式中:

  • -a)将DataGrid的 * 大小列的宽度设置为0。
  • -b)在数据网格上调用UpdateLayout()方法。
  • -c)将数据网格的 * 大小列的宽度设置回新的DataGridLength(1,DataGridLengthUnitType.Star)

示例XAML:

<Window x:Class="DataGridTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <CollectionViewSource x:Key="MyObjectCollection" />
    </Window.Resources>
    <DockPanel>
        <Button DockPanel.Dock="Bottom" Content="Click to Make Item 1s Text Longer" Click="Button_Click" />
        <Grid>
            <DataGrid x:Name="dg" ItemsSource="{Binding Source={StaticResource MyObjectCollection}}" AutoGenerateColumns="False" TargetUpdated="dg_TargetUpdated">
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding First}" Width="1*"/>
                    <DataGridTextColumn Binding="{Binding Last, NotifyOnTargetUpdated=True}"  Width="Auto" />
                </DataGrid.Columns>
            </DataGrid>
        </Grid>

    </DockPanel>
</Window>

示例代码隐藏:

using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.ComponentModel;

namespace DataGridTest
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private ObservableCollection<MyObject> myObjectList = new ObservableCollection<MyObject>();

        public MainWindow()
        {
            InitializeComponent();
            (this.FindResource("MyObjectCollection") as CollectionViewSource).Source = this.myObjectList;
            this.myObjectList.Add(new MyObject() { First = "Bob", Last = "Jones" });
            this.myObjectList.Add(new MyObject() { First = "Jane", Last = "Doe" });
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            this.myObjectList[0].Last = "BillyOBrian";
        }

        private void dg_TargetUpdated(object sender, DataTransferEventArgs e)
        {
            dg.Columns[0].Width = 0;
            dg.UpdateLayout();
            dg.Columns[0].Width = new DataGridLength(1, DataGridLengthUnitType.Star);
        }
    }

    public class MyObject : INotifyPropertyChanged
    {
        private string firstName;
        public string First
        {
            get { return this.firstName; }
            set
            {
                if (this.firstName != value)
                {
                    this.firstName = value;
                    NotifyPropertyChanged("First");
                }
            }
        }

        private string lastName;
        public string Last
        {
            get { return this.lastName; }
            set
            {
                if (this.lastName != value)
                {
                    this.lastName = value;
                    NotifyPropertyChanged("Last");
                }
            }
        }

        public MyObject() { }

        #region -- INotifyPropertyChanged Contract --

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        #endregion INotifyPropertyChanged Contract
    }
}
frebpwbc

frebpwbc2#

我的listview也有类似的问题,我在stackoverflow上的how-to-autosize-and-right-align-gridviewcolumn-data-in-wpf上找到了解决方案。
在我的例子中,它将这段代码添加到列表视图绑定到的可观察集合的collectionchanged事件处理程序中:

void listview_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) {
        // this is a listview control
        GridView view = this.View as GridView;
        foreach(GridViewColumn c in view.Columns) {
            if(double.IsNaN(c.Width)) {
                c.Width = c.ActualWidth;
            }
            c.Width = double.NaN;
        }
    }

它对我很有效,尽管有时用户可以注意到列上的" Flink "。

7bsow1i6

7bsow1i63#

如果需要,WPF将调整数据网格的列宽设置为Auto,即:内容无法完整显示。因此,当内容的宽度缩小时,列不会调整大小,因为内容仍然可以完整显示。
我认为强制wpf重新计算列宽的唯一方法是强制它们全部为0,然后在后面的代码中返回auto,并抛出一个或两个updateLayout(),但这不是很好的编程:-/
基本上,在您代码后面:

foreach (DataGridColumn c in dg.Columns)
    c.Width = 0;

// Update your DG's source here

foreach (DataGridColumn c in dg.Columns)
    c.Width = DataGridLength.Auto;

你可能需要一个dg.UpdateLayout()或两个地方在那里(更新和设置回到自动可能后)

hmtdttj4

hmtdttj44#

解决此问题的一种方法是在样式设置中定义列的width属性,并将该设置绑定到要绑定到的对象的属性。

<DataGridTextColumn Binding="{Binding Change}" ElementStyle="{StaticResource ChangeColumnStyle}"/>

在资源字典中:

<Style TargetType="{x:Type DataGridTextColumn }" x:Key="ChangeColumnStyle">
   <Setter Property="Width" Value="{Binding ColumnWidth}"
</Style>

ColumnWidth应该是对象的一个属性。现在,如果您从'Change'属性的setter中更新此属性(通过使用一些自定义的算法,将字体等内容考虑在内),并调用:

RaisePropertyChanged("ColumnWidth");

它应该会更新您的栏宽。

public int Change
   {
      get { return m_change; }
      set
      {
         if (m_change != value)
         {
            m_change = value;
            ColumnWidth = WidthAlgo(numberOfCharacters);
            RaisePropertyChanged("Change");
            RaisePropertyChanged("ColumnWidth");
         }
      }
   }
vtwuwzda

vtwuwzda5#

你试过这个吗?

<DataGridTextColumn Binding="{Binding Path= Id}"  Header="ID" IsReadOnly="True" Width="1*" />

相关问题