2011-06-22 23 views
7

Może to być oczywiste ... Jak mogę odwołać się do elementów XAML później w tym samym pliku XAML?Jak odwołać się do definicji wiersza/kolumny w Grid.Row/Grid.Column?

Przykład:

<Grid.RowDefinitions> 
    <RowDefinition Height="661*" Name="someGridRow" /> 
    <RowDefinition Height="230*" Name="someOtherGridRow"/> 
</Grid.RowDefinitions> 

Potem zdefiniować różne kontrole wewnątrz sieci i chciałbym odwołać te wiersze po imieniu, a nie numer:

<RichTextBox Grid.Row="someGridRow" ... /> 

Bo jeśli używam Grid.Row="0" na wiele kontrolek, a następnie dodając wiersz przed pierwszym wierszem, muszę ręcznie zmienić wszystkie odniesienia do Grid.Row="1".

Dzięki.

EDIT:

Dzięki odpowiedzi Czytałem trochę na XAML.

Po tym wszystkim, to jest możliwe, aby odwoływać się do poprzedniego elementu wg nazwy widocznie:

Grid.Row="{Binding ElementName=someGridRow}" 

lub

Grid.Row="{x:Reference someGridRow}" 

ale to nie rozwiązuje problemu całkowicie, ponieważ Grid.Row wymaga int , podczas gdy niektóreGridRow nie jest int, to System.Windows.Controls.RowDefinition.

Więc potrzebna jest odpowiednikiem XAML z

Grid.Row = grid.RowDefinitions.IndexOf(someGridRow) 

który w kod związany byłby napisany

Grid.SetRow(richTextBox, grid.RowDefinitions.IndexOf(someGridRow)) 

lub zrobić wiązanie Grid.Row do nieruchomości, na obiekcie grid, która ma ścieżkę "RowDefinitions.IndexOf" z parametrem someGridRow:

PropertyPath path = new PropertyPath("RowDefinitions.IndexOf", someGridRow); 
Binding binding = new Binding() { ElementName = "grid", Path = path }; 
richTextBox.SetBinding(Grid.RowProperty, binding); 

(to faktycznie nie działa w C#, więc muszę być robi coś złego, chociaż Grid.SetRow powyżej działa)

XAML 2009 definiuje <x:Arguments> do wywołania konstruktorów, które mają parametry. Jeśli to działało w WPF XAML, to coś podobnego by działało, jak przypuszczam?

<Grid.Row> 
    <Binding ElementName="grid"> 
    <Binding.Path> 
     <PropertyPath> 
     <x:Arguments> 
      RowDefinitions.IndexOf 
      <Binding ElementName="someGridRow"/> 
     </x:Arguments> 
     </PropertyPath> 
    </Binding.Path> 
    </Binding> 
</Grid.Row> 

gdzie <Binding ElementName="someGridRow"/> można również zastąpić <x:Reference Name="someGridRow"/> w XAML 2009.

+0

myślę, że wszystko będzie działać jak nigdy ścieżce nieruchomości nie pozwala na wywoływanie metod, takich jak 'IndexOf'. –

+0

W porządku, poddaję się ... – SemMike

Odpowiedz

14

Dla lulz:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows.Markup; 
using System.Windows.Controls; 
using System.Windows; 

namespace Test.MarkupExtensions 
{ 
    class GridDefinitionExtension : MarkupExtension 
    { 
     public string Name { get; set; } 

     public GridDefinitionExtension(string name) 
     { 
      Name = name; 
     } 

     public override object ProvideValue(IServiceProvider serviceProvider) 
     { 
      var refExt = new Reference(Name); 
      var definition = refExt.ProvideValue(serviceProvider); 
      if (definition is DefinitionBase) 
      { 
       var grid = (definition as FrameworkContentElement).Parent as Grid; 
       if (definition is RowDefinition) 
       { 
        return grid.RowDefinitions.IndexOf(definition as RowDefinition); 
       } 
       else 
       { 
        return grid.ColumnDefinitions.IndexOf(definition as ColumnDefinition); 
       } 
      } 
      else 
      { 
       throw new Exception("Found object is neither a RowDefinition nor a ColumnDefinition"); 
      } 
     } 
    } 
} 
<Grid Width="200" Height="200" 
     xmlns:me="clr-namespace:Test.MarkupExtensions"> 
    <Grid.RowDefinitions> 
     <RowDefinition Name="row1" /> 
     <RowDefinition Name="row2" /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Name="col1" /> 
     <ColumnDefinition Name="col2" /> 
    </Grid.ColumnDefinitions> 
    <Border Background="Lime" Grid.Row="{me:GridDefinition row1}" Grid.Column="{me:GridDefinition col1}" /> 
    <Border Background="Red" Grid.Row="{me:GridDefinition row2}" Grid.Column="{me:GridDefinition col1}" /> 
    <Border Background="Yellow" Grid.Row="{me:GridDefinition row1}" Grid.Column="{me:GridDefinition col2}" /> 
    <Border Background="Blue" Grid.Row="{me:GridDefinition row2}" Grid.Column="{me:GridDefinition col2}" /> 
</Grid> 
+0

Dobry sposób obejścia tego ograniczenia poprzez MarkupExtensions. –

+0

@Reed Copsey: Dziękuję :) –

+0

Wielkie dzięki! W ogóle nie wiedziałem o rozszerzeniach znaczników lub konwerterach, czytam je teraz na MSDN. Myślę, że faktycznie użyję tego rodzaju rzeczy (nie tylko "dla lulz"), to sprawia, że ​​jestem już lepszy jak XAML ... – SemMike

2

To, niestety, nie działa.

Załączone właściwości (np .: Grid.Row) są używane przez siatkę do obsługi własnego układu, a sposób, w jaki został zaprojektowany, należy wprowadzić numer.

Niestety zmiana liczb podczas wstawiania wiersza jest dość powszechna w rozwoju XAML. Jedna opcja - Możesz wstawić dodatkowe "zero wysokości" wierszy, które są nieużywane, a później używać ich, jeśli wiesz, że będziesz dodawać wiersze.

+0

Dzięki. Dlaczego nie jest to takie proste? Coś w rodzaju 'Grid.Row =" {x: Name someGridRow} "' powinno zostać zaimplementowane ... – SemMike

+0

@SemMike: Podejrzewam, że to z powodu tego, jak to działa. Grid bada swoje dzieci w Grid.Row i nie ma prawdziwego powiązania ... Wszelkie nazwy musiałyby być wykonane z nietypowych identyfikatorów bezpieczeństwa i mogły prowadzić do dziwnych problemów. –

+0

Cóż, z 'Name =" someName "' możesz już odwoływać się do pozycji w kodzie, więc dlaczego nie w samym XAML? Nie jest to mniej "typem bezpiecznym" w XAML niż w C# ... w każdym razie nie jest to możliwe, więc kwestia jest dyskusyjna, dziękuję za szybkie wyrzucenie mnie z nędzy! – SemMike

Powiązane problemy