Как я могу использовать родительский элемент управления контентом из подчиненной привязки? - PullRequest
0 голосов
/ 13 апреля 2010

У меня есть следующий код:

<DataTemplate DataType="{x:Type vm:SectionViewModel}">
    <ScrollViewer>
        <ItemsControl ItemsSource="{Binding ViewModels}">
        </ItemsControl>
    </ScrollViewer>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:StringViewModel}">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
        </Grid.RowDefinitions>
       <Label Name="Left" Grid.Row="0" Grid.Column="0" Content="{Binding Label}"/>
       <TextBox Name="Right" HorizontalAlignment="Stretch" Grid.Row="0" Grid.Column="1" Text="{Binding Value}"/>
    </Grid>
</DataTemplate>

Свойство ViewModels, привязанное к SectionViewModel ItemsControl, представляет собой список StringViewModel. Я хочу вставить каждый StringViewModel в какой-то элемент управления контентом в ItemsControl. В настоящее время у меня есть только каждая StringViewModel для создания своей Grid, но это оставляет вещи без выравнивания. Я хотел бы вставить эти элементы в какой-то элемент управления контентом в ItemsControl, он не обязательно должен быть сеткой, но он должен быть внутри ItemsControl. Как я могу это сделать? Я также слежу за MVVM, используя MVVM Light.

РЕДАКТИРОВАТЬ: я изменил XAML, чтобы отразить, как у меня в настоящее время его настройки.

Ответы [ 2 ]

2 голосов
/ 15 апреля 2010

Если вы хотите контролировать ширину в содержащем шаблоне, вы можете использовать унаследованное вложенное свойство:

public class WidthInformation
{
   // Use propa snippet to create LabelWidth property with this metadata:
   ... RegisterAttached("LabelWidth", typeof(double), typeof(WidthInformation), new FrameworkPropertyMetadata
   {
     Inherits = true
   });
}

Будет использоваться так:

<DataTemplate DataType="{x:Type vm:SectionViewModel}">      
  <ScrollViewer>      
    <ItemsControl ItemsSource="{Binding ViewModels}"
                  local:WidthInformation.LabelWidth="60" />
  </ScrollViewer>      
</DataTemplate>      
<DataTemplate DataType="{x:Type vm:StringViewModel}">      
  <DockPanel>
    <Label Content="{Binding Label}"
           Width="{Binding Path=(local:WidthInformation.LabelWidth)"/>      
    <TextBox Text="{Binding Value}"/>      
  </DockPanel>
</DataTemplate>

Использование DockPanel приведет к тому, что ширина TextBox автоматически заполнит оставшееся пространство.

С другой стороны, если вы хотите, чтобы два столбца имели одинаковый процентный размер по отношению друг к другу, вы можете использовать размер звездочек для столбцов:

<DataTemplate DataType="{x:Type vm:StringViewModel}">      
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="2*" />
      <ColumnDefinition Width="3*" />
    </Grid.ColumnDefinitions>
    <Label Content="{Binding Label}" />      
    <TextBox Text="{Binding Value}" Grid.Column="1" />      
  </DockPanel>
</DataTemplate>

Очень простое решение заключается в жестком кодировании ширины внутри DockPanel вместо использования присоединенного свойства:

<DataTemplate DataType="{x:Type vm:StringViewModel}">      
  <DockPanel>
    <Label Content="{Binding Label}" Width="80" />
    <TextBox Text="{Binding Value}"/>      
  </DockPanel>
</DataTemplate>

Наконец, если вам нужно настроить ширину в зависимости от размера этикетки, вы можете использовать сетку с общим размером:

<DataTemplate DataType="{x:Type vm:SectionViewModel}">      
  <ScrollViewer>      
    <ItemsControl ItemsSource="{Binding ViewModels}"
                  Grid.IsSharedSizeScope="true" />
  </ScrollViewer>      
</DataTemplate>      
<DataTemplate DataType="{x:Type vm:StringViewModel}">      
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" SharedSizeGroup="Label" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Label Content="{Binding Label}" />      
    <TextBox Text="{Binding Value}" Grid.Column="1" />      
  </DockPanel>
</DataTemplate>

WPF просто полон возможностей!

1 голос
/ 14 апреля 2010

Будет проще изменить ваш DataTemplate (для SectionViewModel), чтобы использовать ListBox вместо ваших более общих элементов управления. Как только вы это настроите, измените ваш DataTemplate, чтобы он был присоединен к ListBox.

К сожалению, нет действительно простого способа настроить элементы управления, как вы описываете, не вдаваясь в гораздо более сложные макеты. Я бы порекомендовал настроить его следующим образом, а затем, если вам нужно привязать определенную ширину для ваших столбцов, присоедините ее к своим родительским элементам управления (или установите свойство, которое определяет максимальную ширину и пусть все они привязываются к этому). 1003 *

    <ListBox ItemsSource="{Binding Path=ViewModels}">
        <ListBox.ItemTemplate>
            <DataTemplate DataType="{x:Type vm:StringViewModel}">
                <StackPanel Orientation="Horizontal">
                    <Label x:Name="Left" Content="{Binding Label}" Width="{Binding ElementName=SourceControlHere, Path=WidthToBindTo}"/>
                    <TextBox x:Name="Right" HorizontalAlignment="Stretch" Text="{Binding Value}" Width="{Binding ElementName=SourceControlHere, Path=WidthToBindTo2}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
...