Как ссылаться на определение строки / столбца в Grid.Row / Grid.Column? - PullRequest
9 голосов
/ 23 июня 2011

Это может быть очевидно ... Как я могу ссылаться на элементы XAML позже в том же файле XAML?

Пример:

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

Затем я определяю различные элементы управления внутри сетки, и я хотел бы ссылаться на эти строки по имени, а не по номеру:

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

Потому что, если я использую Grid.Row="0" на многих элементах управления, то, когда я добавляю строку перед первой строкой, я должен вручную изменить все ссылки на Grid.Row="1".

EDIT

Благодаря ответам, которые я немного читаю на XAML.

В конце концов, существует возможность ссылаться на предыдущий элемент по имени, по-видимому:

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

или

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

но это не решает проблему полностью, потому что Grid.Row требует int, тогда как someGridRow не является int, это System.Windows.Controls.RowDefinition.

Итак, нужен XAML-эквивалент

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

который в коде будет написан

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

или выполните привязку Grid.Row к свойству объекта grid, который имеет путь "RowDefinitions.IndexOf" с параметром someGridRow:

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

(это на самом деле не работает в C #, поэтому я, должно быть, что-то делаю не так, хотя Grid.SetRow выше работает)

XAML 2009 определяет <x:Arguments> для вызова конструкторов, имеющих параметры. Если бы это работало в WPF XAML, то что-то подобное сработало бы?

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

, где <Binding ElementName="someGridRow"/> также можно заменить на <x:Reference Name="someGridRow"/> в XAML 2009.

Ответы [ 2 ]

15 голосов
/ 23 июня 2011

Для лулзов:

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>
2 голосов
/ 23 июня 2011

Это, к сожалению, не работает.

Присоединенные свойства, о которых идет речь (например, Grid.Row), используются сеткой для обработки своего собственного макета, и в соответствии с тем, как он спроектирован, вы должны ввести число.

К сожалению, изменение чисел при вставке строки довольно распространено в разработке XAML. Один из вариантов - вы можете добавить дополнительные строки «нулевой высоты», которые не используются, а затем использовать их, если знаете, что собираетесь добавлять строки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...