come impostare tutte le altezze riga del DataGrid wpf quando un'altezza di righe viene regolata

StackOverflow https://stackoverflow.com/questions/1299064

  •  18-09-2019
  •  | 
  •  

Domanda

Im utilizzando il DataGrid WPF e sono alla ricerca di un modo per impostare l'altezza su tutte le righe quando l'utente regola uno di loro. So che il datagrid ha una proprietà RowHeight che imposta tutte l'altezza delle righe in una volta, ma il come di cattura un'altezza singola riga modificata mi sfugge

È stato utile?

Soluzione

Sono arrivato a questo per tentativi ed errori, così a lungo asino si sta utilizzando una fonte di dati ItemsSource dovrebbe funzionare bene. Dovrebbe funzionare con righe virtuali e provoca soltanto una breve pausa visiva e passa sopra (questo sembra dovuto principalmente alla colonna autogenerazione modo può essere evitato).

Come hack andare ha il vantaggio della semplicità e l'uso della meccanica, che non si prevede di cambiare.

L'euristica sul innesco dell'azione utente potrebbe essere migliorata, ma non è ancora fallito su di me.

using Microsoft.Windows.Controls;
using Microsoft.Windows.Controls.Primitives;

public static class DataGridExtensions
{
    public static void LinkRowHeightsToUserChange(this DataGrid dataGrid)
    {
        double? heightToApply = null;
        bool userTriggered = false;

        if (dataGrid.RowHeaderStyle == null)
            dataGrid.RowHeaderStyle = new Style(typeof(DataGridRowHeader));
        if (dataGrid.RowStyle == null)
            dataGrid.RowStyle = new Style(typeof(DataGridRow));

        dataGrid.RowStyle.Setters.Add(new EventSetter()
        {
            Event = DataGridRow.SizeChangedEvent,
            Handler = new SizeChangedEventHandler((r, sizeArgs) =>
            {
                if (userTriggered && sizeArgs.HeightChanged)
                        heightToApply = sizeArgs.NewSize.Height;
            })
        });
        dataGrid.RowHeaderStyle.Setters.Add(new EventSetter()
        {
            Event = DataGridRowHeader.PreviewMouseDownEvent,
            Handler = new MouseButtonEventHandler(
                (rh,e) => userTriggered = true)
        });
        dataGrid.RowHeaderStyle.Setters.Add(new EventSetter()
        {
            Event = DataGridRowHeader.MouseLeaveEvent,
            Handler = new MouseEventHandler((o, mouseArgs) =>
            {
                if (heightToApply.HasValue)
                {
                    userTriggered = false;
                    var itemsSource = dataGrid.ItemsSource;
                    dataGrid.ItemsSource = null;
                    dataGrid.RowHeight = heightToApply.Value;
                    dataGrid.ItemsSource = itemsSource;
                    heightToApply = null;
                }
            })
        });
    }

Altri suggerimenti

Non ci sono eventi che potrebbero essere utilizzati direttamente per questo. Che cosa si potrebbe fare è utilizzare un altro evento che viene generato quando si ridimensiona le righe e le altre cose. L'evento sto pensando in questo momento è PreviewMouseUp, che è il rilascio quando si rilascia il pulsante del mouse ovunque se si DataGrid.

Che cosa si potrebbe fare è quando l'evento viene generato, si potrebbe verificare l'altezza della riga di tutti i tuoi file e trovare quello che è diverso, quindi aggiornare tutte le righe con esso.

@Aran

  

ti ricordi la logica alla base di questo?

Vi posso dire: se si rimuove entrambe le linee di disinserire e resettare la fonte voci (che rallenta infatti l'intero processo un po '), la riga si ridimensiona avrà la sua altezza definitiva impostato

.

Sembra quando si ridimensiona una riga, si modifica direttamente la sua altezza, e questo sostituisce qualsiasi valore impostato alla proprietà RowHeight di DataGrid per questa riga in particolare. Quindi, in pratica, ecco cosa si può ottenere:

dataGrid di RowHeight = 20

si modifica l'altezza di una riga (diciamo il 5 °) per 30 => Altezza di questa riga è impostato su 30 e RowHeight del DataGrid è impostata a 30. Tutto guardando bene finora.

Ora, in altezza modifica di un'altra fila di nuovo a 20 (dire che il 2 ° fila). si Impostare l'altezza di questa riga a 20 e il DataGrid'RowHeight a 20, che mette tutte le altre righe a 20, ad eccezione del 5 ° fila, che rimane a 30. (perché era stato costretto a questo valore prima)

svuotare la sorgente e la reimpostazione costringe ogni riga per essere ricaricato e prendere RowHeight del dataGrid in considerazione, che elimina il problema.

Per quanto ne so non c'è evento che viene generato quando si ridimensiona l'altezza di una riga.

Il mio primo suggerimento sarebbe quello di impostare l'RowStyle al fine di creare un legame (OneWay) tra la proprietà altezza della DataGridRow e proprietà RowHeight del datagrid, ma se si controlla l'altezza della riga dopo il ridimensionamento, è invariato, l'ActualHeight è la proprietà che contiene della riga "reale" di altezza quando si ridimensiona, e ActualHeight non può essere impostato perché "non ha un accesso set accessibile".

Dopo aver provato questo ho pensato: Da dove viene ActualHeight di DataGridRow prende il suo valore da?

Mi sono ricordato questo postale che spiega come rilevare quale cella e la riga ma ho cliccato e mostra anche modello predefinito albero visuale del DataGrid.

per tentativi ed errori (utilizzando l'immagine albero visuale nel link qui sotto) ho trovato che era DataGridCellPresenter che memorizzato l'altezza che veniva utilizzato (in realtà io non sono sicuro al 100% su questo, è stata la prima classe che aveva l'altezza cambiata la struttura ad albero visuale dal DataGridCell).

A quanto pare DataGrid non espone l'API per ottenere il DataGridCellsPresenter da un DataGridRow (come ho scoperto qui )

Quindi il mio primo approccio è stato quello di ottenere tutte le DataGridCellPresenter nel DataGrid (attraverso la struttura ad albero visuale) dopo che è stata popolata e programatically creare un legame tra la proprietà Height della DataGridPresenter e la proprietà RowHeight del DataGrid.

Ecco il codice per farlo (il mio nome dell'istanza del DataGrid è dataGrid1):

Come tutte le DataGridCellPresenter:

    void GetAllDataGridCellPresenters(DependencyObject parent, List<DataGridCellsPresenter> presenters) 
    {
        int numberOfChildren = VisualTreeHelper.GetChildrenCount(parent);         
        for (int i = 0; i < numberOfChildren; i++)
        {
            if (VisualTreeHelper.GetChild(parent, i) is DataGridCellsPresenter)
            {
                presenters.Add(VisualTreeHelper.GetChild(parent, i) as DataGridCellsPresenter);
            }
            else if (VisualTreeHelper.GetChild(parent, i) != null)
            {
                GetAllDataGridCellPresenters(VisualTreeHelper.GetChild(parent, i), presenters);
            }
            else
                return;
        }
    }

Impostazione le associazioni programatically su ognuna di esse (chiamare questo quando l'evento Loaded viene sollevata dal DataGrid):

    void SetBindingInDataGridPresenter()
    {
        List<DataGridCellsPresenter> presenters = new List<DataGridCellsPresenter>();
        GetAllDataGridCellPresenters(dataGrid1, presenters);
        foreach (DataGridCellsPresenter presenter in presenters)
        {    
            Binding binding = new Binding("RowHeight");
            binding.Source = dataGrid1;
            binding.Mode = BindingMode.TwoWay;
            presenter.SetBinding(DataGridCellsPresenter.HeightProperty, binding);
        }
    }

(Nota: L'impostazione il legame come OneWayToSource non ha funzionato, io davvero non so perché, sono probabilmente manca qualcosa di ovvio qui ...)

Questo ha funzionato ... sorta di ... perché ho usato albero visuale per ottenere il DataGridCellsPresenter ho ricevuto solo quelle visibili:. P, ma questo dimostra che si può fare in questo modo

Così, finalmente, il modo giusto per farlo sarebbe quello di fornire il modello di controllo DataGrid, può essere altrettanto quella di default se non con i dati di proprietà Altezza del DataGridCellsPresenter legati alla proprietà RowHeight del DataGrid.

So che questo non mostra esattamente come farlo, ma devi solo imparare (così faccio: P) ridefinire modello di un controllo ; in qualche modo ottenere il modello predefinito DataGrid (o se si sta già utilizzando un altro allora grande, probabilmente sapete più di me su di esso e sanno già come farlo, al fine di ottenere la proprietà DataGridCellsPresenter Altezza legata automaticamente alla proprietà RowHeight DataGrid) e cambiarlo con quel pizzico di magia che ottiene entrambe le proprietà di altezza vincolati.

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