如何从子绑定中使用父内容控件?

发布于 2024-08-28 22:06:09 字数 1160 浏览 5 评论 0原文

我当前有以下代码:

<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>

绑定到SectionViewModel ItemsControl 的ViewModels 属性是StringViewModel 的列表。我想将每个 StringViewModel 插入 ItemsControl 中的某种内容控件中。目前,我只是让每个 StringViewModel 来制作自己的网格,但这使得事情没有对齐。我想将这些项目插入到 ItemsControl 中的某种内容控件中,它不一定必须是网格,但它应该位于 ItemsControl 内。我该怎么做?我也在关注 MVVM,使用 MVVM Light。

编辑:我修改了 XAML 以反映我当前的设置方式。

I have the following code currently:

<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>

The ViewModels property bound to SectionViewModel ItemsControl is a list of StringViewModel. I want to insert each StringViewModel into some sort of content control in the ItemsControl. Currently I just have each StringViewModel to make its own Grid, but that leaves things unaligned. I'd like to insert these items into some sort of content control in ItemsControl, it doesn't necessarily have to be a grid, but it should be within the ItemsControl. How can I do this? I'm also following MVVM, using MVVM Light.

EDIT: I modified the XAML to reflect how I currently have it setup.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

聊慰 2024-09-04 22:06:09

如果您想控制包含模板中的宽度,您可以使用继承的附加属性:

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 充满了可能性!

If you want to control the width in the containing template you can use an inherited attached property:

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

It would be used thusly:

<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>

The use of a DockPanel will cause the TextBox width to automatically fill the remaining space.

On the other hand, if you want the two columns to be the same percentage size relative to each other, you could use star sizing on the columns:

<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>

A very simple solution is to hard-code the width inside the DockPanel instead of using an attached property:

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

Lastly, if you need the width to adjust based on label size you can use a grid with shared sizing:

<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 is just full of possibilities!

夜未央樱花落 2024-09-04 22:06:09

最简单的方法是更改​​您的 DataTemplate(对于 SectionViewModel)以使用 ListBox 而不是那里更通用的控件。设置完成后,将数据模板更改为附加到列表框。

不幸的是,没有真正简单的方法来设置您所描述的控件,而无需进入更复杂的布局。我建议像这样设置它,然后如果您需要绑定到列的特定宽度,请将其附加到您的父控件(或设置一个确定最大宽度的属性并将它们全部绑定到该属性)。

    <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>

It will be easiest to change your DataTemplate (for SectionViewModel) to use a ListBox instead of your more generic controls there. Once you have that set up, then change your DataTemplate to be attached to the ListBox.

Unfortunately, there's no really easy way to set up the controls like you are describing without getting into much more complex layouts. I would recommend setting it up like this, then if you need to bind to a certain width for your columns, attach it to your parent controls (or set up a property that determines the maximum width and have them all bind to that).

    <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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文