制作 DataTemplate 拉伸中的最后一个文本框

发布于 2024-12-03 02:56:01 字数 1613 浏览 0 评论 0原文

我有一个 ItemsControl:

<Border Grid.Row="1" Margin="20" BorderBrush="AliceBlue" BorderThickness="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
   <ItemsControl Margin="10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding SelectedEventHistoryEntryCollection}" ItemTemplateSelector="{StaticResource computerEventHistoryDataTemplateSelector}"/>
</Border>

带有一些数据模板。我正在测试第一个模板:

<DataTemplate x:Key="DetailsDataTemplate">
        <Grid>
            <Label Width="150" HorizontalAlignment="Left" VerticalAlignment="Top" Content="{x:Static resx:Resources.Label_ServiceDept}"/>
            <TextBox Margin="110,0,0,0" Width="200" IsReadOnly="True" Text="{Binding ServiceDepartment}" VerticalAlignment="Top" HorizontalAlignment="Left"/>

            <Label Width="150" Margin="0,40,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Content="{x:Static resx:Resources.Label_SLA}"/>
            <TextBox Margin="110,40,0,0" Width="200" IsReadOnly="True" Text="{Binding SLA}" VerticalAlignment="Top" HorizontalAlignment="Left"/>

            <Label Width="150" Margin="0,80,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Content="{x:Static resx:Resources.Label_Details}"/>
            <TextBox Margin="110,80,10,10" IsReadOnly="True" TextWrapping="Wrap" Text="{Binding Details}"/>
        </Grid>
    </DataTemplate>

我希望数据模板中的最后一个文本框用完剩余空间,但我尝试的任何方法都不起作用。我怎样才能让这个不合作的文本框伸展?

编辑:删除了文本框上的高度属性。

I have an ItemsControl:

<Border Grid.Row="1" Margin="20" BorderBrush="AliceBlue" BorderThickness="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
   <ItemsControl Margin="10" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding SelectedEventHistoryEntryCollection}" ItemTemplateSelector="{StaticResource computerEventHistoryDataTemplateSelector}"/>
</Border>

With some datatemplates. I'm testing the first template:

<DataTemplate x:Key="DetailsDataTemplate">
        <Grid>
            <Label Width="150" HorizontalAlignment="Left" VerticalAlignment="Top" Content="{x:Static resx:Resources.Label_ServiceDept}"/>
            <TextBox Margin="110,0,0,0" Width="200" IsReadOnly="True" Text="{Binding ServiceDepartment}" VerticalAlignment="Top" HorizontalAlignment="Left"/>

            <Label Width="150" Margin="0,40,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Content="{x:Static resx:Resources.Label_SLA}"/>
            <TextBox Margin="110,40,0,0" Width="200" IsReadOnly="True" Text="{Binding SLA}" VerticalAlignment="Top" HorizontalAlignment="Left"/>

            <Label Width="150" Margin="0,80,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Content="{x:Static resx:Resources.Label_Details}"/>
            <TextBox Margin="110,80,10,10" IsReadOnly="True" TextWrapping="Wrap" Text="{Binding Details}"/>
        </Grid>
    </DataTemplate>

I would like the last Textbox in the datatemplate to use up the remaining space, but nothing I tried works. How can I get this uncooperateive TextBox to stretch?

Edit: Removed the Height Property on the Textbox.

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

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

发布评论

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

评论(4

初熏 2024-12-10 02:56:01

使用 LastChildFill="true" 将网格更改为 DockPanel
然后,您可以去掉所有 Margin 并让 WPF 自动进行布局。

Change the grid to a DockPanel with LastChildFill="true".
You can then get rid of all of the Margins and let WPF do the layout automatically.

土豪 2024-12-10 02:56:01

使用 而不是

DockPanel 中的最后一项使用剩余空间。

Use a <DockPanel> instead of a <Grid>.

The last item in the DockPanel uses remaining space.

生生不灭 2024-12-10 02:56:01

通常,我将 与星号大小调整 * 结合使用,而不是此类布局的边距。

更新1:(为了清晰起见,已删除)

更新2:当我遇到这样的情况时,我无法弄清楚在哪里应用绑定或模板,我会尝试备份并以不同的方式看待问题。我几乎总是把它带回 MVVM 模式。在这种情况下,您的模型就是您的 EventHistory 对象。您的 ViewModel 有一个 ObservableCollection。您的视图只是绑定到该集合。因此,要获得这样的内容:

enter image description here

您可以在视图中使用类似的内容:

<Grid>

    <Grid.RowDefinitions>
        <RowDefinition Height="1*" />
        <RowDefinition Height="8" />
        <RowDefinition Height="1.5*" />
    </Grid.RowDefinitions>

    <DataGrid Grid.Row="0" AutoGenerateColumns="True" 
                ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" 
                HorizontalGridLinesBrush="DarkGray" VerticalGridLinesBrush="DarkGray" />

    <GridSplitter Grid.Row="1" 
                    Background="Transparent"
                    HorizontalAlignment="Stretch" VerticalAlignment="Stretch"   />

    <Border Grid.Row="2" BorderBrush="DarkGray" BorderThickness="1" CornerRadius="3" Padding="8">

        <Grid>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

            <Label Grid.Row="0" Grid.Column="0" Content="Status" />
            <TextBox Grid.Row="0" Grid.Column="1" Margin="0,0,0,8" Text="{Binding Path=Status}" />

            <Label Grid.Row="1" Grid.Column="0" Content="Detailed Description" />
            <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}" />

        </Grid>
    </Border>
</Grid>

这就是很好——因为这就是你想要实现的目标。屏幕底部的 2 个标签和文本框上的绑定不必是任何数据模板的一部分。它们是视图的一部分(屏幕截图中红色边框内的所有内容)。所有的大小调整都有效,一切都很好。如果您确实想将内容移至 DataTemplate 中,这可能是可能的,但此时这似乎更自然。

注意:创建视图(红色边框内的区域)后,我将其托管在主窗口中,根据屏幕截图在右侧留下了一个区域。我还对网格分割器、星形调整大小和边距进行了一些自由操作,这样东西就可以占据所有可用空间,同时保持如图所示的比例。

希望这有帮助!

Generally, I use <Grid.RowDefinitions> and <Grid.ColumnDefinitions> in conjunction with star sizing * instead of margins for this type of layout.

UPDATE 1: (Removed for clarity)

UPDATE 2: When I wind up in situations like this where I can’t figure out where to apply a binding or a template I try to back up and look at the problem differently. I almost always take it back to the MVVM pattern. In this case, your Model is your EventHistory object. Your ViewModel has an ObservableCollection<EventHistory>. And your View is simply binding to that collection. So, to get something like this:

enter image description here

You would use something like this for your View:

<Grid>

    <Grid.RowDefinitions>
        <RowDefinition Height="1*" />
        <RowDefinition Height="8" />
        <RowDefinition Height="1.5*" />
    </Grid.RowDefinitions>

    <DataGrid Grid.Row="0" AutoGenerateColumns="True" 
                ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" 
                HorizontalGridLinesBrush="DarkGray" VerticalGridLinesBrush="DarkGray" />

    <GridSplitter Grid.Row="1" 
                    Background="Transparent"
                    HorizontalAlignment="Stretch" VerticalAlignment="Stretch"   />

    <Border Grid.Row="2" BorderBrush="DarkGray" BorderThickness="1" CornerRadius="3" Padding="8">

        <Grid>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

            <Label Grid.Row="0" Grid.Column="0" Content="Status" />
            <TextBox Grid.Row="0" Grid.Column="1" Margin="0,0,0,8" Text="{Binding Path=Status}" />

            <Label Grid.Row="1" Grid.Column="0" Content="Detailed Description" />
            <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}" />

        </Grid>
    </Border>
</Grid>

And that is just fine -- because that is what you are trying to achieve. The bindings on the 2 labels and textboxes at the bottom of the screen don’t have to be part of any data template. They are part of the view (everything inside the red border in the screenshot). All of the resizing works and everything is good. If you really want to move things into a DataTemplate, it is probably possible, but this seemed more natural at this point.

NOTE: After creating the View (area inside the red border) I hosted it in the main window leaving an area to the right as per your screenshot. I also took a few liberties with a grid splitter, star resizing and margins so things would take up all of the available space while maintaining the pictured proportions.

Hopefully that helps!

坏尐絯℡ 2024-12-10 02:56:01

我的第一个答案的理解有点慢。在意识到你的追求之后,我认为这种方法是不正确的。另外,我认为使用 DataTemplates 无法轻松实现您想要的目标。但是,我确实认为您有几个选择:

  1. 检查 Prism 因为它擅长做诸如构建复合材料之类的事情应用程序。然而,对于这个问题来说,这似乎太过分了。因此,更直接的方法可能是...
  2. 为您拥有的每个单独的详细信息视图构建自定义控件,然后编写一些自定义逻辑来根据需要加载每个视图。您将像这样设置它...

您的主网格和详细信息视图主机(即 ContentControl)将设置如下所示:

<Grid Background="Transparent">

    <Grid.RowDefinitions>
        <RowDefinition Height="1*" />
        <RowDefinition Height="8" />
        <RowDefinition Height="1.5*" />
    </Grid.RowDefinitions>

    <DataGrid Grid.Row="0" />

    <GridSplitter Grid.Row="1" Background="Transparent"
                    HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  />

    <Border Grid.Row="2" BorderBrush="DarkGray" BorderThickness="1" CornerRadius="3" Padding="8">
        <ContentControl Grid.Row="2" x:Name="myContent" />            
    </Border>

</Grid>

并且您个人详细信息视图的每个自定义控件将设置如下所示:

<UserControl x:Class="WpfApplication1.CustomUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Label Grid.Row="0" Grid.Column="0" Content="Status" />
        <Label Grid.Row="1" Grid.Column="0" Content="Description" />

        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Status}" />
        <TextBox Grid.Row="1" Grid.Column="1" TextWrapping="Wrap" Text="{Binding Description}" />

    </Grid>
</UserControl>

在运行时,在 DataGrid 中选择一行,您必须使用如下代码加载正确的用户控件:

myContent.Content = new CustomUserControl();

每个自定义控件都必须使用星号调整大小等,以使布局看起来正确 - 这是你的问题想要什么。显然还有很多接线需要完成。

那应该会给你你想要的东西。很抱歉第一个答案跑来跑去!

I was a little slow on the uptake with my first answer. After realizing what you were after I don't think that approach was correct. Also, I don't think you can easily achieve what you're after using DataTemplates. However, I do think you have a few options:

  1. Check into Prism since is is good at doing things like building composite applications. However, it seems like WAY overkill for this problem. So, a more direct approach may be...
  2. Build out custom controls for each separate detail view you have and then write some custom logic to load each view as needed. You would set it up like this...

You main grid and your details view host (i.e. the ContentControl) would be set up something like this:

<Grid Background="Transparent">

    <Grid.RowDefinitions>
        <RowDefinition Height="1*" />
        <RowDefinition Height="8" />
        <RowDefinition Height="1.5*" />
    </Grid.RowDefinitions>

    <DataGrid Grid.Row="0" />

    <GridSplitter Grid.Row="1" Background="Transparent"
                    HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  />

    <Border Grid.Row="2" BorderBrush="DarkGray" BorderThickness="1" CornerRadius="3" Padding="8">
        <ContentControl Grid.Row="2" x:Name="myContent" />            
    </Border>

</Grid>

And each of your custom controls for your individual detail views would be set up something like this:

<UserControl x:Class="WpfApplication1.CustomUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <Label Grid.Row="0" Grid.Column="0" Content="Status" />
        <Label Grid.Row="1" Grid.Column="0" Content="Description" />

        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Status}" />
        <TextBox Grid.Row="1" Grid.Column="1" TextWrapping="Wrap" Text="{Binding Description}" />

    </Grid>
</UserControl>

At run time a row is selected in your DataGrid, you would have to load the correct user control with some code like this:

myContent.Content = new CustomUserControl();

Each of your custom controls would have to use star sizing, etc. to get the layouts to look right - which is what you were after with your question. Obviously there is still a lot of wireup that would need to be done.

That should give you what you are after. Sorry for the run-around on the first answer!

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