Domanda

Uso della WPF DataGrid ho la necessità di cambiare vari display e le relative proprietà di un DataGridCell - come primo piano, FontStyle, IsEnabled e così via - in base al valore relativo della proprietà dell'oggetto cellulare.

Ora, questo è facile da fare in codice, ad esempio (utilizzando una collezione osservabile della ObservableDictionaries):

  var b = new Binding("IsLocked") { Source = row[column], Converter = new BoolToFontStyleConverter() };
  cell.SetBinding(Control.FontStyleProperty, b);

e funziona bene, ma non riesco a vedere come fare questo in XAML dal momento che riesco a trovare alcun modo per impostare Percorso per la proprietà di un oggetto cella.

Una tentativi XAML è:

<Setter Property="FontStyle">
    <Setter.Value>
        <MultiBinding Converter="{StaticResource IsLockedToFontStyleConverter}" Mode="OneWay" UpdateSourceTrigger="PropertyChanged">
              <Binding />
              <Binding RelativeSource="{x:Static RelativeSource.Self}"/>
        </MultiBinding>
    </Setter.Value>
</Setter>

, ma non v'è alcun legame con il È bloccato proprietà

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
    var row = (RowViewModel) values[0];
    var cell = (DataGridCell) values[1];
    if (cell != null && row != null)
    {
        var column = DataGridMethods.GetColumn(cell);
        return row[column].IsLocked ? "Italic" : "Normal";
    }

    return DependencyProperty.UnsetValue;
}

Si noti che una versione precedente restituito row [col] .IsLocked e impostare il FontStyle utilizzando un DataTrigger ma un oggetto restituito non è databound.

Nota, naturalmente, che l'applicazione non sa cosa le colonne sono in fase di progettazione.

Infine di DataTable sono troppo inefficienti per le mie esigenze, ma sarei interessato a vedere come questo è fatto con DataTable in ogni caso, se v'è una tale soluzione per loro, questo potrebbe essere utile altrove (anche se preferisco utilizzando collezioni).

Sicuramente questo è un problema comune e io sono un noobie WPF cercando di andare tutti MVVM sul mio progetto, ma questo problema mi frena rispetto al utilizzando il WPF DataGrid.

È stato utile?

Soluzione

Bene qui è la soluzione più semplice che ho trovato. (In realtà ho avuto prima che ho postato questo e l'altra domanda, ma è stato chi espone a tali solution.Since un hanno sentito niente altro qui e solo nel caso in cui si tratta di chiunque altro si trova ad affrontare lo stesso problema, ho pensato di condividerlo.)

Mettere un riferimento all'oggetto cella nella proprietà Tag DataGridCell. Lo faccio con una combinazione di XAML e di un codice vincolante all'interno di un convertitore come segue:

   <Setter Property="Tag">
       <Setter.Value>
           <MultiBinding Converter="{StaticResource CellViewModelToTagConverter}" Mode="OneWay" UpdateSourceTrigger="PropertyChanged">
              <Binding />
              <Binding RelativeSource="{x:Static RelativeSource.Self}"/>
          </MultiBinding>
       </Setter.Value>
   </Setter>

e

 public class CellViewModelToTagConverter : IMultiValueConverter
 {
     public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
     {
        var row = values[0] as RowViewModel;
        var cell = values[1] as DataGridCell;
        if (row != null && cell != null)
        {
            var column = DataGridMethods.GetColumn(cell);
            // hack within hack!!! (using tag way is itself a hack?)
            var b = new Binding("Self") {Source = row[column]};
            cell.SetBinding(FrameworkElement.TagProperty, b);
            //...
            //return row[column];
            return DependencyProperty.UnsetValue;
        }
        return DependencyProperty.UnsetValue;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

Si può dire quello che penso di questa soluzione dai miei commenti all'interno del convertitore. (Ho dovuto aggiungere una proprietà Sé all'oggetto cellulare e fare auto = Questo nel costruttore).

Ancora consente mia DataGrid codifica del tutto MVVM - se si accetta che quello che ho fatto all'interno del convertitore è coerente con MVVM. Comunque funziona!

Quindi, facendo in questo modo riesco a vedere e gestire tutto da XAML come il controllo come vincolanti solo su alcune colonne posizionando il XAML all'interno delle cellstyles colonna pertinente (che non sta facendo questo tramite DataGrid.CellStyle).

In ogni caso, un esempio di utilizzo è

<Style.Triggers>
      <DataTrigger Value="true" Binding="{Binding RelativeSource={RelativeSource Self}, Path=Tag.IsLocked}">
            <Setter Property="FontStyle" Value="Italic"/>
            <Setter Property="IsEnabled" Value="False"/>
       </DataTrigger>
 </Style.Triggers>

A livello XAML è sia semplice ed elegante, IMHO (in particolare per le varie descrizioni comandi e popup per i quali faccio un utilizzo intenso delle proprietà dell'oggetto delle cellule). Comunque sono sicuro che ci sia un modo migliore di fare questo, è là?

Speriamo che questo tutto va via quando posso usare Net 4.0 e dinamici oggetti, ma per questo progetto non posso.

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