c# - 如何使用子绑定(bind)中的父内容控件?

标签 c# wpf data-binding mvvm datatemplate

我目前有以下代码:

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

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

编辑:我修改了 XAML 以反射(reflect)我当前的设置方式。

最佳答案

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

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

关于c# - 如何使用子绑定(bind)中的父内容控件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2631195/

相关文章:

c# - WPF SelectedItem 颜色在列表失去焦点时消失

asp.net - 回发时 ListView 的 LayoutTemplate 中的数据绑定(bind)表达式

c# - 如何在代码中创建一个 SuperSocket WebSocket 服务器

c# - 在属性中,如何获取它所附加的方法的名称?

c# - 如何在 c# 中使用行索引和列索引从 datagridview 获取单元格值?

c# - Directory.GetFiles 方法上的 searchPattern 逻辑

c# - 在 Visual Studio 中创建 WPF UI 的建议

c# - 快速将类属性公开为可绑定(bind)

asp.net - CompositeControl 中的 DropDownList 是否应该记住所选项目?

android - Unresolved reference : ActivityMainBinding in Android Studio 3. 6