Ширина столбца DataGrid не обновляется автоматически - PullRequest
23 голосов
/ 05 апреля 2011
<DataGridTextColumn Binding="{Binding Name}" Width="*"/>
<DataGridTextColumn Binding="{Binding Change}" Width="Auto"/>

Когда значение Change обновляется, его столбец не обновляется, чтобы соответствовать новому значению. Таким образом, столбец остается слишком маленьким, а значение обрезается.
Есть идеи?

Ответы [ 5 ]

55 голосов
/ 13 апреля 2011

DataGrid будет увеличивать размеры столбцов, чтобы они соответствовали по мере увеличения длины данных, но он не будет автоматически уменьшать размеры столбцов при уменьшении длины данных.В вашем примере вы правильно выравниваете столбец «Изменить» и используете оставшееся пространство для столбца «Имя».

Теперь, когда свойство «Изменить» становится достаточно большим, чтобы его увеличитьширина столбца, столбец «Имя» отказывается сокращаться, чтобы приспособиться, поэтому вы должны принудительно обновить сами.

Следующие шаги должны сделать это для вас (я включил пример приложениядля демонстрации):

1) В привязках DataGridTextColumn (все, кроме столбца размером *) установите NotifyTargetUpdated = True.
2) В вашей DataGrid добавьте обработчик к событию TargetUpdated.
3) В вашем обработчике событий TargetUpdated:
- a) Установите ширину столбца размера * DataGrid равной 0.
- b) Вызовите метод UpdateLayout () для DataGrid.
- c) Установите ширину * размерного столбца DataGrid обратно на новый 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
    }
}
1 голос
/ 15 апреля 2011

WPF просто изменит размер столбца сетки данных, установленный на Авто, если это необходимо, т. Е. Содержимое не может быть отображено полностью. Поэтому, когда ширина содержимого уменьшается, размер столбца не изменяется, так как содержимое все еще можно увидеть полностью.

единственный способ, которым я могу заставить 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() или два где-то там (после обновления и настройки обратно на авто, вероятно)

0 голосов
/ 13 апреля 2011

Вы пробовали это?

<DataGridTextColumn Binding="{Binding Path= Id}"  Header="ID" IsReadOnly="True" Width="1*" />
0 голосов
/ 12 апреля 2011

Одним из способов решения этой проблемы является определение свойства width столбца в настройке стиля и привязка этого параметра к свойству объекта, к которому вы привязываете.

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

В вашем ResourceDictionary:

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

ColumnWidth должен быть свойством вашего объекта. Теперь, если вы обновите это свойство из установщика вашего свойства «Изменить» (с помощью некоторого самоопределяемого алгоритма, принимая во внимание такие вещи, как шрифт) и вызовите:

RaisePropertyChanged("ColumnWidth");

Это должно обновить ширину вашего столбца.

 public int Change
   {
      get { return m_change; }
      set
      {
         if (m_change != value)
         {
            m_change = value;
            ColumnWidth = WidthAlgo(numberOfCharacters);
            RaisePropertyChanged("Change");
            RaisePropertyChanged("ColumnWidth");
         }
      }
   }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...