Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何从子绑定使用父内容控件?_C#_Wpf_Data Binding_Mvvm_Datatemplate - Fatal编程技术网

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

C# 如何从子绑定使用父内容控件?,c#,wpf,data-binding,mvvm,datatemplate,C#,Wpf,Data Binding,Mvvm,Datatemplate,我目前有以下代码: <DataTemplate DataType="{x:Type vm:SectionViewModel}"> <ScrollViewer> <ItemsControl ItemsSource="{Binding ViewModels}"> </ItemsControl> </ScrollViewer> </DataTemplate> <DataTemp

我目前有以下代码:

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


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

将数据模板(对于SectionViewModel)更改为使用列表框而不是更通用的控件是最简单的。设置好后,将DataTemplate更改为附加到列表框

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


将数据模板(对于SectionViewModel)更改为使用列表框而不是更通用的控件是最简单的。设置好后,将DataTemplate更改为附加到列表框

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


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

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: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}"
                  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将导致文本框宽度自动填充剩余空间

另一方面,如果希望两列的相对百分比大小相同,可以对列使用星形大小:

<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内的宽度,而不是使用附加属性:

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: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只是充满了可能性

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

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: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}"
                  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将导致文本框宽度自动填充剩余空间

另一方面,如果希望两列的相对百分比大小相同,可以对列使用星形大小:

<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内的宽度,而不是使用附加属性:

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: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),但我会使用继承的附加属性,并将StackPanel更改为DockPanel,以便文本框可以填充可用空间。或者在网格上按比例调整大小。我想我最好在一个实际的答案中详细说明一下。为了简单起见,你的答案会更好:)好答案(+1)但我会使用继承的附加属性,并将StackPanel更改为DockPanel,以便文本框可以填充可用空间。或者在网格上按比例调整大小。我想我最好在一个实际的答案中详细说明一下。为了简单起见,你的答案会更好:)我最终实现了这个完全不同的(使用数据网格),但这基本上就是我想要的。这肯定会有帮助,因为我似乎总是做一些需要这样做的事情。非常感谢!我最终实现了完全不同的(使用DataGrid),但这本质上就是我想要的。这肯定会有帮助,因为我似乎总是做一些需要这样做的事情。非常感谢!