该实际场景比较常见于,当存在多个用户控件页面拼成一个窗体,因为实际控件对应窗体的宽度并不能确定,也不是那种能指定的宽度或者高度,比如窗体分导航区域和内容区域,左侧导航区域可以直接指定宽度,而右侧内容区域则是使用Auto或者*的宽度。
在WPF中,尝试将一个控件的宽度绑定到其父级用户控件的实际宽度(ActualWidth)时,会遇到一些挑战。因为 ActualWidth和ActualHeight 是只读属性,并且它们是在布局过程之后计算出来的,这可能导致绑定延迟或不更新的问题。为了确保子控件能够正确地响应父控件大小的变化,根据实际情况使用如下方式。
 
方法1:使用相对宽度和星号单位
最简单的方法是让子控件自动填充可用空间,而不是显式地绑定到父控件的 ActualWidth。可以通过设置子控件的 HorizontalAlignment 属性为 Stretch 或使用在布局Grid的宽度用 * 星号单位来实现这一点。
如下:
<rubyer:Card x:Name="cardNotice" Grid.Row="1"
Height="120"
Padding="5"
HorizontalAlignment="Stretch" <!-- 设置为 Stretch -->
HorizontalContentAlignment="Center">
<!-- Card 内容 -->
</rubyer:Card>
Card内容里部分,可用StackPanel容器包装,StackPanel容器自动适应内部空间的宽度和高度,在结合HorizontalAlignment="Stretch"就可以实现,将rubyer:Card这个控件自动适配宽度和用户控件的宽度一样,当然也需要该rubyer:Card占据用户控件全部的Column。
或:
<Grid x:Name="homeGrid"
Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="350" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="5" />
</Grid.RowDefinitions>
</Grid>
 
方法2:使用 RelativeSource 绑定
如果确实需要基于父控件的实际宽度进行绑定,可以尝试使用 RelativeSource 绑定来引用父控件的 ActualWidth。
如下:
<UserControl x:Class="YourNamespace.PlanMoudelView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SizeChanged="PlanMoudelView_SizeChanged">
<Grid>
<rubyer:Card x:Name="cardNotice" Grid.Row="1"
Height="120"
Width="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ActualWidth, Mode=OneWay}"
Padding="5"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center">
<!-- Card 内容 -->
</rubyer:Card>
</Grid>
</UserControl>
主要为:Width="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ActualWidth, Mode=OneWay}"
方法3:使用 SizeChanged 事件处理程序
另一种方法是在父控件的 SizeChanged 事件中手动调整子控件的宽度。这种方法适用于更复杂的情况,但通常不是首选,因为 WPF 布局系统应该能够处理大多数场景。
private void PlanMoudelView_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (cardNotice != null)
{
cardNotice.Width = this.ActualWidth; // 'this' 指向 PlanMoudelView
}
}
 
方法4:使用 MultiBinding 和转换器
如果需要更复杂的逻辑,比如保留一定的边距或比例,可以使用 MultiBinding 结合 IMultiValueConverter 来计算子控件的宽度。
<rubyer:Card x:Name="cardNotice" Grid.Row="1"
Height="120"
Padding="5"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Center">
<rubyer:Card.Width>
<MultiBinding Converter="{StaticResource WidthConverter}">
<Binding RelativeSource="{RelativeSource AncestorType=UserControl}" Path="ActualWidth"/>
<Binding Source="{x:Static sys:Double.NaN}"/> <!-- 如果需要额外参数 -->
</MultiBinding>
</rubyer:Card.Width>
<!-- Card 内容 -->
</rubyer:Card>
注意:确保父容器允许子控件扩展
确保包含 Card 控件的父容器(例如 Grid)没有限制子控件的尺寸。检查是否有固定的高度或宽度、MaxWidth 或 MaxHeight 等可能影响布局的属性。
 
总结
通常情况下,使用相对宽度(如 * 星号单位)和适当的 HorizontalAlignment 是最简单有效的方法,可以确保子控件随着父控件的大小变化而自动调整。如果需要更精确的控制,可以考虑使用 RelativeSource 绑定或其他高级技术。确保父容器也支持子控件的动态尺寸调整非常重要。
最后附上,绑定后宽度减数的转换器,因为通常不能直接用子控件跟父控件完全等宽或等高,肯定需要有偏差:

/// <summary>
/// 控件宽度减法转换器
/// 可用于子控件绑定父控件宽度做减法
/// </summary>
public class SubtractValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double parentWidth = (double)value;
double subtractValue = double.Parse(parameter.ToString());
return parentWidth - subtractValue;
} public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
} 在用户控件页面增加绑定资源:
<UserControl.Resources>
<converter:SubtractValueConverter x:Key="subtractValueConverter" />
</UserControl.Resources>
然后,在绑定时增加转换器的使用:
Width="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ActualWidth, Mode=OneWay, Converter={StaticResource subtractValueConverter}, ConverterParameter=20}"

转换器代码

实际下图中右下角的列表Card使用实例:

<UserControl x:Name="VehicleQueueView"
x:Class="WpfAppMom.Views.Plan.VehicleQueue"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:WpfAppMom.Controls"
xmlns:converter="clr-namespace:WpfAppMom.Converter"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:local="clr-namespace:WpfAppMom.Views.Plan"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:rubyer="http://rubyer.io/winfx/xaml/toolkit"
xmlns:viewModels="clr-namespace:WpfAppMom.ViewModels.Plan"
d:DataContext="{d:DesignInstance Type=viewModels:VehicleQueueViewModel}"
d:DesignHeight="450"
d:DesignWidth="800"
mc:Ignorable="d">
<UserControl.Resources>
<converter:SubtractValueConverter x:Key="subtractValueConverter" />
</UserControl.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding LoadedCommand}" />
</i:EventTrigger>
<i:EventTrigger EventName="Closed">
<i:InvokeCommandAction Command="{Binding CancelCommand}" CommandParameter="{Binding ElementName=VehicleQueueView}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<controls:ControlDisplay x:Name="QueueControl"
Title="车辆队列"
HorizontalAlignment="Stretch"
rubyer:PanelHelper.Spacing="10">
<Grid Width="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ActualWidth, Mode=OneWay, Converter={StaticResource subtractValueConverter}, ConverterParameter=20}"
Height="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=ActualHeight, Mode=OneWay, Converter={StaticResource subtractValueConverter}, ConverterParameter=55}"
HorizontalAlignment="Left"
rubyer:GridHelper.RowDefinitions="45, *, 50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0"
Margin="5"
HorizontalAlignment="Left"
rubyer:PanelHelper.Spacing="5"
Orientation="Horizontal">
<Button Width="110"
rubyer:ButtonHelper.IconType="PhoneLine"
Content="呼叫AGV" />
<Button Width="110"
rubyer:ButtonHelper.IconType="FileShredLine"
BorderBrush="{StaticResource ButtonBorderForegroundBrush}"
Content="打印表单"
FontStyle="Normal"
Foreground="{StaticResource ButtonFontForegroundBrush}"
Style="{StaticResource OutlineButton}" />
<Button Width="110"
rubyer:ButtonHelper.IconType="GitRepositoryCommitsLine"
BorderBrush="{StaticResource ButtonBorderForegroundBrush}"
Content="报工"
Foreground="{StaticResource ButtonFontForegroundBrush}"
Style="{StaticResource OutlineButton}" />
</StackPanel>
<DataGrid x:Name="DataGrid" Grid.Row="1"
HorizontalContentAlignment="Center"
rubyer:ControlHelper.CornerRadius="{DynamicResource AllContainerCornerRadius}"
rubyer:ControlHelper.FocusedBrush="{DynamicResource Primary}"
rubyer:ControlHelper.FocusedForegroundBrush="{DynamicResource WhiteForeground}"
rubyer:ControlHelper.MaskOpacity="1"
rubyer:DataGridHelper.ClickToEdit="False"
rubyer:DataGridHelper.Loading="{Binding IsLoading}"
rubyer:HeaderHelper.Background="{StaticResource DataGridTitleBrackgroudBrush}"
rubyer:HeaderHelper.FontFamily="宋体"
rubyer:HeaderHelper.FontSize="15"
rubyer:HeaderHelper.FontWeight="DemiBold"
rubyer:HeaderHelper.Foreground="{StaticResource DataGridTitleFontBrush}"
rubyer:HeaderHelper.HorizontalAlignment="Center"
AutoGenerateColumns="True"
CanUserAddRows="False"
GridLinesVisibility="Horizontal"
IsReadOnly="False"
ItemsSource="{Binding Datas}"
RowHeight="40">
<DataGrid.Columns>
<rubyer:DataGridSelectCheckBoxColumn Width="85"
Binding="{Binding IsSelected}"
Header="全选" />
</DataGrid.Columns>
</DataGrid>
<rubyer:PageBar Grid.Row="2"
Margin="0 10 20 0"
IsShowPageSize="True"
IsShowTotal="True"
ItemsDock="Left"
PageIndexChanged="PageBar_PageIndexChanged"
PageSizeChanged="PageBar_PageSizeChanged"
PageSizeCollection="10, 20, 30, 50"
Style="{StaticResource TextPageBar}"
Total="1000" />
</Grid> </controls:ControlDisplay>
</UserControl>

用户控件代码

WPF页面中将一个控件的宽度绑定到其父级用户控件的实际宽度的更多相关文章

  1. 【WPF学习】第六十四章 构建基本的用户控件

    创建一个简单用户控件是开始自定义控件的好方法.本章主要介绍创建一个基本的颜色拾取器.接下来分析如何将这个控件分解成功能更强大的基于模板的控件. 创建基本的颜色拾取器很容易.然而,创建自定义颜色拾取器仍 ...

  2. WPF之路——用户控件对比自定义控件UserControl VS CustomControl)

    将多个现有的控件组合成一个可重用的“组”. 由一个XAML文件和一个后台代码文件. 不能使用样式和模板. 继承自UserControl类. 自定义控件(扩展) 在现有的控件上进行扩展,增加一些新的属性 ...

  3. 【WPF】WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示

    前言: Wpf开发过程中,最经常使用的功能之一,就是用户控件(UserControl)了.用户控件可以用于开发用户自己的控件进行使用,甚至可以用于打造一套属于自己的UI框架.依赖属性(Dependen ...

  4. Asp.net 恢复页面内用户控件内的控件ClientID

    众所周知在Asp.net中如果一个页面添加了一个用户控件(或母版页),那么用户控件内的控件的   ClientID号会被自动添加页面中用户控件的ClientID 即页面中的控件内的控件ClientID ...

  5. 【demo练习四】:WPF用户控件案例

    首先,新建vs中“用户控件(WPF)”,右键项目名 =>"添加"按钮 => 选择“新建项”. 然后选择“用户控件(WPF)” => 起名字 => 点击“添加 ...

  6. WPF 模仿 UltraEdit 文件查看器系列一 用户控件

    WPF 模仿 UltraEdit 文件查看器系列一 用户控件 运行环境:Win10 x64, NetFrameWork 4.8, 作者:乌龙哈里,日期:2019-05-10 章节: 起步 添加用户控件 ...

  7. 033. asp.netWeb用户控件之二将页面转换成web控件和使用Web控件显示热点新闻

    访问Web用户控件的属性 ASP.NET提供的各种服务器控件都有其自身的属性和方法,程序开发人员可以灵活地使用服务器控件中的属性和方法开发程序.在用户控件中,程序开发人员也可以自行定义各种属性和方法, ...

  8. C# winform中自定义用户控件 然后在页面中调用用户控件的事件

    下面是用户控件的代码: using System; using System.Collections.Generic; using System.ComponentModel; using Syste ...

  9. ASP.Net用户控件的使用

    一.概述: 与WEB窗体页相同,程序员可以使用任何文本编辑器创作用户控件,或者使用代码隐藏类开发用户控件.此外,与WEB窗体页一样,用户控件可以在第一次请求时被编译并存储在服务器内存中,从而缩短以后请 ...

  10. 032. asp.netWeb用户控件之一初识用户控件并为其自定义属性

    Web用户控件的优点: 可以将常用的内容或者控件以及控件的运行程序逻辑, 设计为用户控件, 以后便可以在多个页面中重复使用该用户控件, 从而省去许多重复性的工作. 如网页上的导航栏, 几乎每个页面都需 ...

随机推荐

  1. 指针进阶(函数指针)(C语言)

    目录 1. 字符指针变量 2. 数组指针变量 2.1 数组指针变量是什么? 2.2 数组指针变量怎么初始化? 3. 二维数组传参的本质 4. 函数指针变量 4.1 函数指针变量的创建 4.2 函数指针 ...

  2. .NET 8.0 开源在线考试系统(支持移动端)

    前言 推荐一款基于.NET 8.0 免费开源跨平台在线考试系统,系统不仅支持桌面端,还特别优化了移动端的用户体验. 通过本系统可以轻松搭建自己的在线考试平台,实现随时随地的测试与评估. 本文将详细介绍 ...

  3. 4-11.3 C++中的显式类转换

    目录 static_cast 1.用来改变基本类型:一般是高精度转低精度 2.恢复void* 指针类型 const_cast 用来去除底层const(low-level const) reinterp ...

  4. 使用wxpython开发跨平台桌面应用,基类列表窗体的抽象封装处理

    在开发一套系统框架的时候,除了关注实现系统的功能实现外,我们对于系统的各个方面都是应该精益求精,以最少的编码做最好的事情,在开发的各个层次上,包括前端后端,界面处理.后端处理.常用辅助类.控件封装等等 ...

  5. 痞子衡嵌入式:在i.MXRT启动头FDCB里配置串行NOR Flash多个寄存器的注意事项

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是在FDCB里配置串行NOR Flash多个寄存器的注意事项. 关于使用 i.MXRT 启动头 FDCB 来设置 Flash 内部寄存器, ...

  6. golang模板库之fasttemplate

    简介 fasttemplate是一个比较简单.易用的小型模板库.fasttemplate的作者valyala另外还开源了不少优秀的库,如大名鼎鼎的fasthttp,前面介绍的bytebufferpoo ...

  7. MySQL 8.0 为什么会放弃查询缓存?

    什么是查询缓存? 查询缓存就是将一次查询结果存储在内存中,假如下一次查询结果在内存中,就直接在内存中读取. 设计初衷 当然是提高性能,通过缓存来减少解析器.优化器.存储引擎的执行时间. MySQL查询 ...

  8. 鸿蒙UI系统组件01——文本组件(Text/Span)

    如果你也对鸿蒙开发感兴趣,加入"Harmony自习室"吧!点击下面的名片关注公众号. 1.概述 Text是文本组件,是我们开发UI界面中最常见的组件之一,通常用于展示用户的视图,如 ...

  9. 埃尼阿克ENIAC与计算机发展,及信息技术发展史

    一.埃尼阿克ENIAC 第二次世界大战期间,国军方为了研发新型的大炮和导弹,设立了"弹道研究实验室".实验室为了计算炮弹弹道,用了200多人加班加点进行计算,速度依感无法达到军方要 ...

  10. less 常用方法

    介绍 Less 是 CSS 的预处理语言之一,为 CSS 增添了变量.Mixin.函数等特性,使CSS更易于维护扩展. 嵌套(Nesting) .header { .navgation: { font ...