Domanda

Ho due WPF Toolkit DataGrids , vorrei che quando l'utente ridimensionasse la prima colonna nella prima griglia, ridimensionasse la prima colonna nella seconda griglia. Ho provato ad associare la larghezza di DataGridColumn nella seconda griglia alla colonna appropriata nella prima griglia, ma non funziona. Preferirei usare tutto xaml, ma sto bene anche usando il codice dietro.

<tk:DataGrid Width="100" Height="100">
    <tk:DataGrid.Columns>
        <tk:DataGridTextColumn x:Name="Column1" Width="50"/>
    </tk:DataGrid.Columns>
</tk:DataGrid>
<tk:DataGrid Width="100" Height="100">
    <tk:DataGrid.Columns>
        <tk:DataGridTextColumn x:Name="Column1Copy" Width="{Binding Path=ActualWidth, ElementName=Column1}"/>
    </tk:DataGrid.Columns>
</tk:DataGrid>

Ho anche provato a legare a Width anziché ActualWidth , ma nessuno dei due funziona.

Qualsiasi aiuto è molto apprezzato.

È stato utile?

Soluzione

Beh, non penso che sia possibile usare XAML direttamente, ma mi sento ancora come dovrebbe perché DataGridColumn deriva da DependencyObject . Ho trovato un modo per farlo programmaticamente però. Non ne sono entusiasta, ma funziona:

DataGridColumn.WidthProperty.AddValueChanged(upperCol, delegate
{
    if (changing) return;
    changing = true;
    mainCol.Width = upperCol.Width;
    changing = false;
});
DataGridColumn.WidthProperty.AddValueChanged(mainCol, delegate 
{ 
    if (changing) return;
    changing = true;
    upperCol.Width = mainCol.Width; 
    changing = false; 
});

public static void AddValueChanged(this DependencyProperty property, object sourceObject, EventHandler handler)
{
    DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(property, property.OwnerType);
    dpd.AddValueChanged(sourceObject, handler);
}

Altri suggerimenti

Puoi usare il metodo DataGrid LayoutUpdated per manipolare altri oggetti riguardanti la larghezza delle colonne.

private void dataGrid1_LayoutUpdated(object sender, EventArgs e)
{
    for(int i = 0 ; i < dataGrid1.Columns.Count && i < dataGrid2.Columns.Count ; ++i)
        dataGrid2.Columns[i].Width = dataGrid1.Columns[i].ActualWidth;
}

Ho provato questo:

<tk:DataGrid Width="100" Height="100" x:Name="Grid1" Grid.Column="0">
   <tk:DataGrid.Columns>
      <tk:DataGridTextColumn x:Name="Column1" Width="50"/>
   </tk:DataGrid.Columns>
</tk:DataGrid>
<tk:DataGrid Width="100" Height="100" x:Name="Grid2" Grid.Column="1">
   <tk:DataGrid.Columns>
     <tk:DataGridTextColumn x:Name="Column1Copy" Width="{Binding Mode=TwoWay, Path=Columns[0].ActualWidth, ElementName=Grid1}"/>
     </tk:DataGrid.Columns>
</tk:DataGrid>

Tuttavia, sembra che poiché DataGridColumn non derivano da FrameworkElement ma derivano invece da DependencyObject , l'associazione in questo modo non è disponibile .

Se si desidera associare la proprietà Width della colonna in XAML, in 2 DataGrid è necessario eseguire le seguenti operazioni.

Nel primo DataGrid denominare DataGridTextColumn :

<DataGrid>
    <DataGrid.Columns>
        <DataGridTextColumn x:Name="Col1"/>
    </DataGrid.Columns>
</DataGrid>

Nel secondo DataGrid aggiungi un DiscreteObjectKeyFrame che punta alla colonna sopra menzionata come risorsa e usa il Binding seguente in Proprietà su DataGridTextColumn che vuoi " link " ;:

<DataGrid>
    <DataGrid.Resources>
        <DiscreteObjectKeyFrame x:Key="proxyCol1" Value="{Binding ElementName=Col1}"/>
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn  Width="{Binding Path=Value.Width, Mode=TwoWay, Source={StaticResource proxyCol1}}"/>
    </DataGrid.Columns>
</DataGrid>

Ho fatto una rapida soluzione a questo usando un comportamento associato, ispirato dalla risposta Ahmed sopra.

public class DataGridWidthSyncronizerBehavior
{
    public static readonly DependencyProperty SyncronizeWidthWithProperty =
        DependencyProperty.RegisterAttached("SyncronizeWidthWith",
            typeof(DataGrid),
            typeof(DataGridWidthSyncronizerBehavior),
            new UIPropertyMetadata(null, SyncronizeWidthWithChanged));

    public static void SetSyncronizeWidthWith(DependencyObject target, DataGrid value)
    {
        target.SetValue(SyncronizeWidthWithProperty, value);
    }

    public static DataGrid GetSyncronizeWidthWith(DependencyObject target)
    {
        return (DataGrid)target.GetValue(SyncronizeWidthWithProperty);
    }

    private static void SyncronizeWidthWithChanged(DependencyObject obj, DependencyPropertyChangedEventArgs dpargs)
    {
        if (!(obj is DataGrid sourceDataGrid))
            return;

        if (!(sourceDataGrid.GetValue(SyncronizeWidthWithProperty) is DataGrid targetDataGrid))
            return;

        void Handler(object sender, EventArgs e)
        {
            for (var i = 0; i < sourceDataGrid.Columns.Count && i < targetDataGrid.Columns.Count; ++i)
                targetDataGrid.Columns[i].Width = sourceDataGrid.Columns[i].ActualWidth;
        }

        sourceDataGrid.LayoutUpdated -= Handler;
        sourceDataGrid.LayoutUpdated += Handler;
    }
}

XAML:

<DataGrid local:DataGridWidthSyncronizerBehavior.SyncronizeWidthWith="{Binding ElementName=SyncronizedHeaderGrid}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Header 1" 
                            Binding="{Binding Item1}" />
        <DataGridTextColumn Header="Header 2" 
                            Binding="{Binding Item2}"/>
        <DataGridTextColumn Header="Header 3" 
                            Binding="{Binding Item3}"/>
    </DataGrid.Columns>
</DataGrid>

<DataGrid x:Name="SyncronizedHeaderGrid">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Header 1" 
                            Binding="{Binding Item1}" />
        <DataGridTextColumn Header="Header 2" 
                            Binding="{Binding Item2}"/>
        <DataGridTextColumn Header="Header 3" 
                            Binding="{Binding Item3}"/>
    </DataGrid.Columns>
</DataGrid>

Il Second DataGrids, intestazione e larghezza della cella, è ora sincronizzato con la prima larghezza dell'intestazione della griglia.

Ho trovato una soluzione a questo problema e una soluzione davvero interessante :-) È possibile scaricare il toolkit WPF e ottenere il codice di DataGrid. Una volta che hai il codice, tutto ciò che devi fare è cambiare la classe DataGridColumn per ereditare FrameworkElement invece di DependencyObject. Una volta che lo fai - ti rimane solo un problema, il DataContext della colonna non verrà inizializzato poiché la colonna non fa parte dell'albero logico, aggiungendolo all'albero logico risolverebbe questo. Puoi farlo in questo modo: Dove si trova OnColumnInitialization:         void privato OnColumnInitialization (mittente oggetto, EventArgs e)         {
            AddLogicalChild (mittente);         } Ora che fa parte dell'albero logico, hai lo stesso contesto di dati e puoi usare l'associazione su Proprietà larghezza. Se tutti sono associati alla stessa larghezza, hai una sincronizzazione completa della larghezza delle colonne. Questo ha funzionato per me :-) Gili

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top