该实际场景比较常见于,当存在多个用户控件页面拼成一个窗体,因为实际控件对应窗体的宽度并不能确定,也不是那种能指定的宽度或者高度,比如窗体分导航区域和内容区域,左侧导航区域可以直接指定宽度,而右侧内容区域则是使用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. 物理实验霍尔效应判断P/N型半导体笔记

    最近这不要物理实验期末考试了嘛,我火速抄起实验书准备复习. 复习到霍尔效应判断P/N型半导体这一部分时很惊奇地发现网上一会儿还搜不出个明了的总结,也有很多误导性的判断方法.Σ( ° △ °|||)︴ ...

  2. 管中窥豹----从String Intern中观察.NET Core到.NET 8 托管堆的变迁

    简介 https://www.cnblogs.com/lmy5215006/p/18494483 在此文中,研究.NET String底层结构时,我所观察到的情况与<.NET Core底层入门& ...

  3. base64编码图片二进制数据后直接保存在html文件中

    相关内容: 在markdown编辑器中嵌入base64图片 看到一个帖子,那就是base64编码用来http服务中对二进制文件编码,那么可以不可以直接在html文件中使用base64编码后的字符串来表 ...

  4. DCDC电路设计之FB引脚布线

    该随笔从与非网上搬运,原文: 案例讲解,DCDC电源反馈路径的布线规则 下面为正文内容: 在本文中,将对用来将输出信号反馈给电源ic的FB引脚的布线进行说明. 反馈路径的布线 反馈信号的布线在信号布线 ...

  5. 在PyCharm中打包Python项目并将其运行到服务器上的方法

    在PyCharm中打包Python项目并将其运行到服务器上的方法 在PyCharm中打包Python项目并将其运行到服务器上的过程,可以分解为几个关键步骤:创建项目.设置项目依赖.打包项目.配置服务器 ...

  6. MinIO Linux 安装使用 & SpringBoot整合MinIO

    目录 MinIO Linux 安装 单节点部署 创建 systemd 系统启动服务文件 创建环境变量文件 启动MinIO服务 连接到MinIO服务 SpringBoot项目整合MinIO 配置项 工具 ...

  7. 浅析JVM内存结构和6大区域

    内存作为系统中重要的资源,对于系统稳定运行和高效运行起到了关键的作用,Java和C之类的语言不同,不需要开发人员来分配内存和回收内存,而是由JVM来管理对象内存的分配以及对象内存的回收(又称为垃圾回收 ...

  8. 前端实战之使用canvas合并图片

    最近做一个完整的系统,前端中涉及到一个推广图片的生成,其中推广图片是由一个变化的链接生成的二维码与一个固定图片拼接而成 实现demo: qrcode.png:https://images.cnblog ...

  9. 简单端口映射、转发、重定向工具之Rinetd

    ◆一.概述 Rinetd是为在一个Unix和Linux操作系统中为重定向传输控制协议(TCP)连接的一个工具.将 TCP 连接从一个 IP 地址和端口重定向到另一个.它处理文件中/etc/rinetd ...

  10. seldom-platform:颠覆传统的自动化测试平台

    seldom-platform:颠覆传统的自动化测试平台 seldom-platform是一个自动化测试平台,其特点是让会写代码的测试人员能够通过seldom框架高效地完成自动化用例的编写,并将剩下的 ...