c# - personalizar - El ancho de la columna DataGrid no se actualiza automáticamente
editar datagridview c# (6)
¿Has probado esto?
<DataGridTextColumn Binding="{Binding Path= Id}" Header="ID" IsReadOnly="True" Width="1*" />
<DataGridTextColumn Binding="{Binding Name}" Width="*"/>
<DataGridTextColumn Binding="{Binding Change}" Width="Auto"/>
Cuando el valor de Change
actualizaciones, su columna no se actualiza para ajustarse al nuevo valor. Entonces, la columna permanece demasiado pequeña y el valor se recorta.
¿Algunas ideas?
Asegúrese de que la clase que está utilizando para el enlace de datos implemente la interfaz INotifyPropertyChanged y suba un evento PropertyChanged cada vez que se actualice la propiedad Change como en el siguiente ejemplo:
public class SomeDataClass : INotifyPropertyChanged
{
private int m_change;
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
// You can''t use automatic properties here since you need to call RaisePropertyChanged method
public int Change
{
get { return m_change; }
set
{
if (m_change != value)
{
m_change = value;
RaisePropertyChanged("Change");
}
}
}
}
El DataGrid aumentará el tamaño de las columnas para adaptarse a medida que los datos se vuelven más largos, pero no disminuye automáticamente el tamaño de las columnas cuando la longitud de los datos disminuye. En su ejemplo, alinea correctamente la columna ''Cambiar'' y utiliza el resto del espacio para la columna ''Nombre''.
Ahora, cuando una propiedad ''Cambiar'' crece lo suficientemente grande como para aumentar el ancho de la columna, la columna ''Nombre'' se niega a contraerse para acomodarse, por lo que debe forzar una actualización usted mismo.
Los siguientes pasos deberían hacer esto por usted (he incluido una aplicación de muestra en la demostración):
1) En sus Vinculaciones DataGridTextColumn (todas excepto su * columna de tamaño) configure NotifyTargetUpdated = True.
2) En su DataGrid, agregue un controlador al evento TargetUpdated.
3) En su controlador de eventos TargetUpdated:
- a) Establezca el ancho de la columna del tamaño * de DataGrid en 0.
- b) Llamar al método UpdateLayout () en DataGrid.
- c) Establecer el ancho de la columna del tamaño de DataGrid * de nuevo en el nuevo DataGridLength (1, DataGridLengthUnitType.Star)
Ejemplo 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>
Ejemplo de código detrás:
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
}
}
He tenido un problema similar con mi lista de listas, la solución que encontré en how-to-autosize-and-right-align-gridviewcolumn-data-in-wpf aquí en .
En mi caso, estaba agregando esta pieza de código en el controlador de eventos de colección intercambiada de la colección observable a la que estaba sujeta la vista de lista:
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;
}
}
Funciona para mí, aunque a veces el usuario puede notar un "parpadeo" sobre las columnas.
Una forma de resolverlo es definiendo la propiedad de ancho de la columna en una configuración de estilo y vinculando esa configuración a una propiedad del objeto al que se está vinculando.
<DataGridTextColumn Binding="{Binding Change}" ElementStyle="{StaticResource ChangeColumnStyle}"/>
En su ResourceDictionary:
<Style TargetType="{x:Type DataGridTextColumn }" x:Key="ChangeColumnStyle">
<Setter Property="Width" Value="{Binding ColumnWidth}"
</Style>
ColumnWidth debe ser una propiedad de su objeto. Ahora, si actualiza esta propiedad desde el setter de su propiedad ''Cambiar'' (usando algún algoritmo autodefinido, tomando cosas como la fuente en cuenta), y llamando:
RaisePropertyChanged("ColumnWidth");
Debe actualizar el ancho de su columna.
public int Change
{
get { return m_change; }
set
{
if (m_change != value)
{
m_change = value;
ColumnWidth = WidthAlgo(numberOfCharacters);
RaisePropertyChanged("Change");
RaisePropertyChanged("ColumnWidth");
}
}
}
WPF simplemente cambiará el tamaño del ancho de columna de una cuadrícula de datos establecido en Automático si es necesario, es decir, el contenido no se puede mostrar por completo. Entonces, cuando el ancho del contenido se reduce, la columna no cambia de tamaño ya que el contenido aún se puede ver por completo.
la única forma que puedo ver para obligar a wpf a recalcular el ancho de las columnas sería forzarlas a todas a 0 y luego volver a las automáticas en el código de atrás, con una o dos updateLayout () lanzadas, pero esta no es una programación muy buena : - /
básicamente, en tu código detrás:
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;
y probablemente necesite un dg.UpdateLayout()
o dos en algún lugar allí (después de la actualización y la configuración de regreso a auto probablemente)