WPF页面中将一个控件的宽度绑定到其父级用户控件的实际宽度

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

 

 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/865801.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Windows 系统下 Docker 和 Docker Compose 安装配置:一键部署有来开源项目本地环境

在 Windows 系统上安装 Docker 和 Docker Compose,实现一键部署有来开源项目的本地环境,包括单体应用和微服务架构。🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🍃 vue-uniapp-template 🌺 仓库主页: GitCod…

Openfiler iscsi共享存储连接访问配置

Openfiler、iscsi案例说明: 通过openfiler虚拟机模拟iscsi server建立存储共享,测试多路径(multipath)配置。 测试架构:iscsi server网络配置:一、通过firefox浏览器访问openfiler服务配置 1、连接服务配置失败2、修改TLS认证级别3、连接访问openfiler配置服务二、配置op…

SQL Server数据库备份、差异备份、日志备份脚本.250108

1,sp脚本 USE [master] GO /****** Object: StoredProcedure [dbo].[sp_BackupDatabase] Script Date: 2025/1/8 10:43:05 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO-- Author: Amadeus-- Create date: 2021-10-20 exec sp_BackupDatabase L-- Descrip…

JuiceFS 2024:开源与商业并进,迈向 AI 原生时代

即将过去的 2024 年,是 JuiceFS 开源版本推出的第 4 年,企业版的第 8 个年头。回顾过去这一年,JuiceFS 社区版依旧保持着快速成长的势头,GitHub 星标突破 11.1K,各项使用指标增长均超过 100%,其中文件系统总数量较前一年更是增长了 8.5 倍;企业版同样持续保持高速增长,…

智慧防洪平台:构建城市安全的数字防线

随着全球气候变化的加剧和城市化进程的加快,城市防洪问题日益凸显。智慧防洪平台作为智慧城市建设的重要组成部分,其核心目标是通过集成先进的信息技术和数据分析,实现对城市洪涝灾害的有效预防和应对。本文将深入探讨智慧防洪平台的建设内容,以期为城市安全提供强有力的数…

如何通过数据分析优化电商营销策略和客户体验

一、电商数据的收集 电商平台的数据来源多样,包括用户行为数据、交易数据、客户反馈数据、商品信息数据等。高效的数据收集不仅是数据分析的前提,也是实现精准决策的基础。 1.1 数据收集的主要来源 用户行为数据:用户在电商平台上的每一次点击、浏览、搜索、加入购物车、下单…

CDS标准视图:安排维护计划的调用 I_MAINTENANCEPLANSCHEDULE

视图名称:安排维护计划的调用 I_MAINTENANCEPLANSCHEDULE 视图类型: 视图代码:点击查看代码 @AbapCatalog.compiler.compareFilter: true @AbapCatalog.sqlViewName: IMPLASCHED @AccessControl.authorizationCheck: #CHECK @ClientHandling.algorithm: #SESSION_VARIABLE @…

Bolt.new 30秒做了一个网站,还能自动部署,难道要吊打 Cursor?

大家好,我是汤师爷~ 这篇聊聊 Bolt.new 和 Cursor 的对比。Bolt.new 是一款基于 SaaS 的 AI 编码平台。它由 LLM 驱动的智能体作为底层,并结合 WebContainers 技术,让用户可以直接在浏览器中进行编码和运行。其主要优势包括:支持前后端同时开发; 项目文件夹结构可视化; 环…

Ubuntu20.4安装Docker

一、设置 Docker 存储库 1、更新系统 apt 包索引 更新软件包索引,并且安装必要的依赖软件,来添加一个新的 HTTPS 软件源 # 更新索引 sudo apt-get update# 安装必要的依赖包,使apt能通过HTTPS使用仓库 sudo apt install apt-transport-https ca-certificates curl gnupg-age…

linux 清空catalina.out日志 不需要重启tomcat(五种方法)

今天突然发现图表展示查询条件不能用了,想着可能是日志太多一直没清理导致的,结果一查tomcat的log目录居然已经有1012G,果断删除生成的前几年的日志,发现这些都不大,保留2425年其他都删掉还有956G,仔细一看catalina.out居然有865G,上网查看有没有不关闭tomcat就清空这个…

docker compose的安装.211215

1,安装docker CentOS8 默认是会读取centos.org的mirrorlist的,所以一般来说是不需要配置镜像的。 step 1: 安装必要的一些系统工具 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 dnfstep 2: 更新 container.io 包, 否则可能会报 package docker-ce-3:1…

Failed to start docker.service Unit docker.service not found处理方式.211215

出现该问题的原因是 centos8 中的podman导致的,podman是centos8预装的类似docker的软件 不需要所以直接卸载。 解决方式: dnf remove podman然后重装Docker sudo yum install -y yum-utils device-mapper-persistent-data lvm2 sudo yum-config-manager --add-repo http…