Windows Presentation Foundation或WPF是用于在基于Windows的应用程序中呈现用户界面的子系统。
将属性值从父级用户控件传递到子级的 DependencyProperty
如何将属性(SomeProperty)从ParentUserControl上下文传递到ChildUserControl的DependencyProperty(MyDProperty)? 在 XAML 中,它应该是: 如何将 ParentUserControl 上下文中的 property (SomeProperty) 传递到 ChildUserControl 的 DependencyProperty (MyDProperty)? 在XAML中,应该是: 但是,由于某种原因,MyDProperty 永远不会使用 Parent.DataContext.SomeProperty 设置。 就我而言,我正在传递一个操作,但这并不重要。我认为问题出在绑定上。 家长用户控制: public Action RemoveEsl1 => throw new NotImplementedException(); <uc:ChildUserControl Title="ESL 1" RemoveEslAction="{Binding RemoveEsl1}" DataContext="{Binding Esl1}"/> 子用户控件: public static readonly DependencyProperty RemoveEslActionProperty = DependencyProperty.Register(nameof(RemoveEslAction), typeof(Action), typeof(ChildUserControl), new PropertyMetadata(delegate { })); public Action RemoveEslAction { get => (Action)GetValue(RemoveEslActionProperty); set => SetValue(RemoveEslActionProperty, value); } 我在这里找到了各种技巧,但没有一个适合我或有效。 回答我自己的问题(检查 ParentUserControl): 型号: public class RootModel : ViewModelBase { private ParentModel parentModel = new(); public ParentModel ParentModel { get => parentModel; set => RisePropertyChanged(ref parentModel, value); } } public class ParentModel : ViewModelBase { private ChildModel childModel = new(); public ChildModel ChildModel { get => childModel; set => RisePropertyChanged(ref childModel, value); } public string ParentModelProperty => "Correct value from ParentModel"; } public class ChildModel : ViewModelBase { private string childModelProperty = "Wrong default value from ChildModel"; public string ChildModelProperty { get => childModelProperty; set => RisePropertyChanged(ref childModelProperty, value); } } 主窗口: <Window.DataContext> <model:RootModel/> </Window.DataContext> <uc:ParentUserControl DataContext="{Binding ParentModel}"/> 家长用户控件: <uc:ChildUserControl ChildDependency="{Binding DataContext.ParentModelProperty, RelativeSource={RelativeSource AncestorType=UserControl}}" DataContext="{Binding ChildModel}"/> 子用户控件: <StackPanel> <Label Content="Dependency property:"/> <Label Content="{Binding ChildDependency, RelativeSource={RelativeSource AncestorType=UserControl}}"/> <Separator/> <Label Content="Property:"/> <Label Content="{Binding ChildModelProperty}"/> </StackPanel> public partial class ChildUserControl : UserControl { public static readonly DependencyProperty ChildDependencyProperty = DependencyProperty.Register(nameof(ChildDependency), typeof(string), typeof(ChildUserControl), new ("Wrong default DP value from ChildUserControl")); public string ChildDependency { get => (string)GetValue(ChildDependencyProperty); set => SetValue(ChildDependencyProperty, value); } public ChildUserControl() { InitializeComponent(); } } 这就是如何将属性 (SomeProperty) 从 ParentUserControl 上下文传递到 ChildUserControl 的 DependencyProperty (MyDProperty)。
我有这个问题,我为我的wpf窗口设置了样式,其中一部分用于默认ContextMenu,但仍然有部分默认样式。 我尝试为每种类型的控件设置背景...
C#。 WPF。将函数分配给 Texbox 中的 DataObject.Pasting,保留 MVVM 模式
对于文本框中的 DataObject.Pasting 事件,我想分配位于视图模型(MVVM 模式)中的 TextBoxPasting 函数。不幸的是,该代码不起作用。我使用图书馆:
“StaticResourceExtension”对于 Setter.Value 无效。 - 安装VS2022后出现新错误
我正在创建一个小WPF(自学)。 我相信它是在 VS2021 中创建的,但是我的电脑死了(主板)。 我已经在新电脑上重新安装了所有内容并带来了备份并...
.NET7 或 8 - WPF - 访问 Windows.Storage 抛出 System.TypeInitializationException
我们如何使用为商店打包的 .NET7 或 8 以及 WPF Core 访问 Windows.Storage? 举个例子,我们曾经这样做过: Log.Logger = new LoggerConfiguration() .最低级别.信息...
这个应该很简单,但是我找不到。 目前,我有以下触发器: 这个应该很简单,但是我找不到。 目前,我有以下触发器: <DataTrigger Binding="{Binding warmed, Converter={converters:IsGreaterThan 185}}" Value="False"> 如您所见,有一个与固定值(185)的比较,但我希望它是可变的,所以我尝试了这样的方法: <DataTrigger Binding="{Binding warmed, Converter={converters:IsGreaterThan "{Binding MaxMinutes}" } }" Value="False"> (出于可读性原因,我添加了一些空格。 虽然这应该非常简单,但我似乎没有找到。 有人有想法吗? 预先感谢 P.s.您很快就将此问题标记为重复问题,但重复的问题基于 ConverterParameter。 结果我尝试将自己的情况转换成一个情况,使用这样的ConverterParameter,但是没有成功: <DataTrigger Binding="{Binding warmed, Converter={converters:IsGreaterThan}, ConverterParameter=185}" Value="False"> => 这似乎不起作用。谁能告诉我如何使用 ConverterParameter 将我的情况转换为一种情况? 打开“创建数据绑定”对话框时,我看到的是: 如您所见,没有任何 185 值的痕迹,尽管它在我的解决方案中至关重要。当我将其填写为 ConverterParameter 时,这就是我得到的: <DataTrigger Binding="{Binding warmed, ConverterParameter=185, Converter={converters:IsGreaterThan 185}}" Value="False"> ...并且再次无法声明任何多重绑定(因为我无法通过尝试键入来完成它,所以我尝试使用 Visual Studio“属性”编辑器来获取它)。 编辑:新的一天,新的尝试 再次尝试,这次尝试介绍MultiBinding: <DataTrigger> <DataTrigger.Binding> <MultiBinding> <Binding Path="warmed"/> <Binding Converter="{converters:IsGreaterThan 185}"/> <Binding Value="False"/> </MultiBinding> </DataTrigger.Binding> => 它会产生两条错误消息: XLS0413:在“Binding”类型中找不到属性“Value”。 XDG0012:成员“Value”无法识别或无法访问。 再次感谢 注释是正确的,即不可能直接将 ConverterParameter 与使用纯 XAML 的变量一起使用。 XAML 就是这样不灵活。 虽然 MultiBinding 可以在这里工作,但我认为这是一种冒险的方法(稍后会详细介绍),而且肯定是矫枉过正。相反,我会简单地在视图模型级别处理这个问题,方法是定义一个 bool POCO 属性 WarmEnough,其值源自 Warmed 和 MaxMinutes: public class ViewModel : INotifyPropertyChanged { public bool WarmEnough => this.Warmed >= this.MaxMinutes; private double _warmed; public double Warmed { get { return _warmed; } set { if (_warmed == value) return; _warmed = value; OnPropertyChanged(); OnPropertyChanged(nameof(Warmed)); } } private double _MaxMinutes; public double MaxMinutes { get { return _MaxMinutes; } set { if (_MaxMinutes == value) return; _MaxMinutes = value; OnPropertyChanged(); OnPropertyChanged(nameof(Warmed)); } } public event PropertyChangedEventHandler? PropertyChanged; private void OnPropertyChanged([CallerMemberName] string? name = null) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } } 然后您只需将触发器绑定到 WarmEnough 属性,而不考虑转换器等。 (只要确保您不需要出于某种原因进行双向绑定即可!)这是有效的,因为每当 WarmEnough 或 Warmed 发生更改时,都会引发 MaxMinutes 的属性更改。因此,每当这些属性中的任何一个发生更改时,都会触发 Trigger。 从功能上来说,它与 MultiBinding 相同 - 在 Convert 的 IMultiValueConverter 方法中,你基本上会做我建议你在 WarmEnough 的 getter 中做的同样的事情 - 但问题是值将作为 object 数组进入多转换器,您需要检查和转换其类型,这取决于 XAML 中 Binding 的顺序。如果没有明确的文档,这很容易让未来的您和/或您的继任者陷入困境。 IMO MultiBinding确实最适合所有值都是相同类型并且正确顺序要么明显要么不相关的情况,例如对多个条件进行布尔 AND/OR/XOR 检查、将字符串连接在一起等。可以通过这种方式完成,所以也许克莱门斯会很友善地向我们展示。但我会坚持使用基于视图模型的方法并缩短所有这些。
如何在 bing 地图 wpf c# 上绘制贝塞尔曲线折线?
wpf 的 Bing 地图库似乎不包含任何绘制贝塞尔曲线的帮助器。 它有MapPolyLine,可用于在n个点之间绘制直线。 有什么解决办法吗? 谢谢
将 MenuItem 图标颜色绑定到 MenuItem 的前景
问题 我有一个带有控制模板的 MenuItem,该模板可以更改 MenuItem 的前景,如下所示: 问题 我有一个带有控制模板的 MenuItem,可以更改 MenuItem 的 Foreground,如下所示: <ControlTemplate TargetType="MenuItem"> <StackPanel Background="{Binding Background}" Orientation="Horizontal"> <ContentPresenter Content="{TemplateBinding Icon}"/> <TextBlock Text="{TemplateBinding Header}"/> </StackPanel> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="true"> <Setter Property="Foreground" Value="Red"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> 我想将图标的颜色绑定到该前景色。在这种情况下,图标只是一个圆圈。我尝试了以下绑定: <MenuItem Header="Sub"> <MenuItem.Icon> <Ellipse Width="16" Height="16" Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType=MenuItem}}"/> </MenuItem.Icon> </MenuItem> 但是,这会在应用程序启动时出现以下绑定错误,并且椭圆最终不会被渲染: System.Windows.Data 错误:4:找不到引用“RelativeSource FindAncestor,AncestorType='System.Windows.Controls.MenuItem',AncestorLevel='1'' 进行绑定的源。 BindingExpression:Path=前景;数据项=空;目标元素是“椭圆”(名称=“”);目标属性是“填充”(类型“画笔”) 我还尝试在图标中放置一个虚拟元素,以传播前景并绑定到此: <MenuItem.Icon> <Grid> <TextBlock Name="foregroundCapture"/> <Ellipse Width="16" Height="16" Fill="{Binding Foreground, ElementName=foregroundCapture}"/> </Grid> </MenuItem.Icon> 但这给出了类似的错误: System.Windows.Data 错误:4:找不到引用“ElementName=foregroundCapture”的绑定源。 BindingExpression:Path=前景;数据项=空;目标元素是“椭圆”(名称=“”);目标属性是“填充”(类型“画笔”) 如何才能使绑定生效?仅供参考,图标最终将是资源字典中的一个对象。因此它将无法访问实际的菜单项。 替代解决方案 我可以想到几个替代解决方案。但实际上他们都不是很好: 创建具有 MouseOverIcon 属性的 MenuItem 子类并让触发器使用它。 为每个图标创建自定义控件,并传播 Foreground 属性。这将允许直接在控件内进行直接绑定。 完整示例 <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApplication1" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <Style TargetType="MenuItem"> <Style.Triggers> <Trigger Property="Role" Value="SubmenuItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="MenuItem"> <StackPanel Background="{Binding Background}" Orientation="Horizontal"> <ContentPresenter Content="{TemplateBinding Icon}"/> <TextBlock Text="{TemplateBinding Header}"/> </StackPanel> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="true"> <Setter Property="Foreground" Value="Red"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Trigger> </Style.Triggers> </Style> </Window.Resources> <DockPanel> <Menu DockPanel.Dock="Top"> <MenuItem Header="Header"> <MenuItem Header="Sub"> <MenuItem.Icon> <Grid> <TextBlock Name="foregroundCapture"/> <Ellipse Width="16" Height="16" Fill="{Binding Foreground, ElementName=foregroundCapture}"/> </Grid> </MenuItem.Icon> </MenuItem> </MenuItem> </Menu> <Grid> </Grid> </DockPanel> </Window> 你可以尝试这样的绑定: <Ellipse Width="16" Height="16" Fill="{Binding RelativeSource={RelativeSource Mode=Self}, Path=(TextElement.Foreground)}"/>
从代码中关闭 Material Design DialogHost
我正在尝试找到一种方法来从代码启动活动 DialogHost 的关闭,但无法找到正确的语法。我认为主要的挑战是从类访问 DialogHost
我正在尝试添加嵌套(子)菜单项。显示主菜单项,但不显示子菜单项。显然我缺少一个属性,但无法弄清楚。任何指示将不胜感激......
我的 WPF 测试应用程序(非常简单,只有一个窗口)正在使用第 3 方托管 dll(例如 X.dll)。此托管 dll 使用一些非托管 dll 的 . 假设我编写了一个小型 wpf 应用程序,它仅引用...
尝试安装 Microsoft.Extensions.DependencyInjection 时出现 Sytem.IO.DirectoryNotFoundException
System.IO.DirectoryNotFoundException:找不到路径 \packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.0 uildTransitive/net461/Microsoft.Extensions 的一部分。
WPF - 如何从 DataTemplate 为自定义用户控件设置正确的 DataContext
我正在尝试制作一个自定义用户控件(TSFloorPlanProductDispenserStockViewer)来显示错误代码和供用户交互的按钮列表。在数据模板中 (
MenuItem SubMenu 出现在 ContextMenu 的左侧而不是默认的
这个问题与这里的帖子相关 - 原来的问题已经解决,但随后又出现了另一个问题。 正如您所看到的,MenuItem 出现在错误的一侧 由于上一问题与
我有一个 WPF 窗口,其中一些属性被定义为动态资源,如下所示: 我有一个 WPF 窗口,其中一些属性被定义为动态资源,如下所示: <Window x:Class="LocSample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" MinHeight="350" MinWidth="525" Title="{DynamicResource ResourceKey=ResId_Title}" FlowDirection="{DynamicResource ResId_FlowDirection_Default}" > <Grid> <Label Content="{DynamicResource ResId_FirstName}" /> </Grid> </Window> ResourceDictionary 在运行时加载以反映用户的语言选择。并允许用户即时切换语言。 这在运行时工作正常,但在设计时,不会显示资源定义的属性。我很清楚设计师无法显示它们,因为它们没有在设计时定义。 我需要一种在设计时加载默认值的方法,以便设计师可以显示任何内容。 编辑: 在 Blend 中,您可以针对这种情况使用设计时资源字典文件。 Visual Studio 可以读取该文件,但没有创建该文件的工具。但如果您不害怕项目文件,您可以手动完成。 将文件 DesignTimeResources.xaml 添加到您的项目中。 打开项目文件 (*.csproj) 并找到 DesignTimeResources.xaml 文件的注册。 将此注册替换为以下代码 ResourceDictionary 现在您可以合并文件中所需的所有资源字典。编译器会忽略它,但设计器不会。 请参阅不是我的文章了解更多详情。 抛弃过时且无用的“DesignTimeResources.xaml”,在最新版本(VS 2022)中,您可以使用更强大的<Page Include="Properties\DesignTimeResources.xaml" Condition="'$(DesignTime)'=='true' OR ('$(SolutionPath)'!='' AND Exists('$(SolutionPath)') AND '$(BuildingInsideVisualStudio)'!='true' AND '$(BuildingInsideExpressionBlend)'!='true')"> <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> <ContainsDesignTimeResources>true</ContainsDesignTimeResources> </Page> 前缀来包含您的设计时资源:d: 旁注: <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <d:ResourceDictionary Source="/OTHER_ASSEMBLY;component/Resource/YOUR_DESIGN_TIME_RESOURCE.xaml" /> <ResourceDictionary Source="/styles/YOUR_COMPILED_RESOURCE.xaml" /> <ResourceDictionary Source="/OTHER_ASSEMBLY;component/styles/YOUR_COMPILED_RESOURCE2.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources> 还可以用于设置 Control 上的设计时属性,例如 d:,尽管它未在 IntelliSense 中列出...ps:我确认它可以在最新的 VS 2022 上运行,我不确定它是否可以在较低版本上运行。
是否有与文本框控件的 HTML onCopy 事件等效的 WPF?我想在将文本复制到剪贴板之前进行一些处理。
如何设置RadDocking中RadSplitContainer之间的间距?
我想在我的 WPF 应用程序中更改 RadDocking 的样式。我已经找到了如何更改 RadDocking 中的填充的解决方案,但是任何用于删除或更改空间宽度的属性或解决方案
我正在取消上传,如果时间太长,我决定使用带有取消按钮的启动屏幕 我正在取消上传,如果时间太长,我决定使用带有取消按钮的启动画面 <Window x:Class="App.UploadingSplashScreen" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Name="splashWindow" WindowStyle="None" ResizeMode="NoResize" AllowsTransparency="True" Background="Transparent" ShowInTaskbar="False" Topmost="True" xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" WindowStartupLocation="Manual" SizeToContent="WidthAndHeight"> <StackPanel x:Name="LayoutRoot"> <dx:WaitIndicator x:Name="Indicator" DeferedVisibility="True" > <dx:WaitIndicator.ContentTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding}"/> <TextBlock Text="{Binding Percentage, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/> </StackPanel> </DataTemplate> </dx:WaitIndicator.ContentTemplate> </dx:WaitIndicator> <StackPanel> <Button Content="Cancel" Background="IndianRed" HorizontalAlignment="Right" Click="CancelUpload_OnClick"></Button> </StackPanel> </StackPanel> </Window> 当我点击取消按钮时,取消请求的cancel()将被调用,但每次我尝试时,点击事件总是在请求完成后触发,并且我也收到了响应。如何克服这个问题? private async void CancelUpload_OnClick(object sender, RoutedEventArgs e) { //App.CurrentWindow.TokenSource.Cancel(); App.CurrentWindow.cancelAction?.Invoke(); } 我尝试使用 Action end 调用它,但也没有希望。 我提出的示例请求: App.CurrentWindow.cancelAction = () => { App.CurrentWindow.TokenSource.Cancel(); }; // var response = HttpClient.Instance.PostAsync(GetFileRequestUrl(), content, App.CurrentWindow.TokenSource.Token).Result; // App.CurrentWindow.TokenSource.Token.ThrowIfCancellationRequested(); 您必须正确等待异步方法。当您调用 Task.Result 时,异步方法将同步执行,因为当前线程正在等待 Result 属性返回。总是 await async 方法。 你的代码看起来也很臭。不应涉及任何静态属性或实例。您没有提供足够的上下文来理解您在做什么。 class MainWindow : Window { public static HttpClient SharedHttpClient { get; } = new HttpClient(); private CancellationTokenSource HttpClientCancellationTokenSource { get; set; } private async Task UploadAsync(HttpContent content) { try { // CancellationTokenSource implements IDisposable! // We must dispose it e.g. via the using statement/expression or a finally block or explicitly. using this.HttpClientCancellationTokenSource = new CancellationTokenSource(); string url = GetFileRequestUrl(); // await the async method. Now the user can click the button and execute the cancel operation // *while* the upload is running. await MainWindow.SharedHttpClient.PostAsync(url, content, this.HttpClientCancellationTokenSource.Token); } catch(OperationCanceledException) { // Somebody has cancelled the async task. // TODO::Perform rollback, cleanup etc. // To allow the caller of this operation to handle cancellation too // you can rethrow the exception or swallow it //throw; } finally { // this.HttpClientCancellationTokenSource is already disposed at this point (using expression). // Set variable to NULL so nobody can accidently try to use the disposed instance this.HttpClientCancellationTokenSource = null; } } private async void CancelUpload_OnClick(object sender, RoutedEventArgs e) => this.HttpClientCancellationTokenSource?.Cancel(); }
我有一个应用程序,其中使用 CompositeCommand 来触发一系列子命令。子命令组合起来可能需要 15 秒以上才能完成。当这种情况发生时,我模拟...
WPF:如何创建呈现作为内容传递的控件的 UserControl
我正在尝试创建“Expander”用户控件,以方便隐藏(折叠)另一个用户界面。 现在我有这个: 扩展器用户控件 - XAML: 我正在尝试创建“Expander”用户控件,以方便隐藏(折叠)另一个 UI。 现在我有这个: 扩展用户控件 - XAML: <StackPanel> <TextBlock Text="{Binding Caption, ElementName=root}"/> <ToggleButton Content="{Binding ToggleText}" IsChecked="{Binding Expanded}"/> <ContentControl Visibility="{Binding Expanded, Converter={x:Static root:GlobalConverters.BoolToCollapsedVisibilityConverter}}" Content="{Binding Content, ElementName=root}" /> </StackPanel> 扩展用户控件 - 代码隐藏: public Expander() { InitializeComponent(); DataContext = new ViewModels.ExpanderViewModel(); } public static readonly DependencyProperty CaptionProperty = DependencyProperty.Register("Caption", typeof(string), typeof(Expander), new PropertyMetadata("unkown caption")); public string Caption { get => (string)GetValue(CaptionProperty); set => SetValue(CaptionProperty, value); } public new static readonly DependencyProperty ContentProperty = DependencyProperty.Register("ItemsSource", typeof(object[]), typeof(Expander), new PropertyMetadata(Array.Empty<EmptyContent>())); public new object[] Content { get => (object[])GetValue(ContentProperty); set => SetValue(ContentProperty, value); } 扩展器使用 - 查看: <DataTemplate DataType="{x:Type viewModels:OrdersListModeViewModel}"> <StackPanel> <controls:Expander Caption="Orders"> <ItemsControl ItemsSource="{Binding Orders}" /> </controls:Expander> </StackPanel> </DataTemplate> 我面临两个问题: 设计师正在显示此错误屏幕: 我尝试删除 obj 和 bin 目录,但没有帮助。 我在 Expander.xaml 中遇到绑定错误: 我不明白为什么“controls:Expander”元素内容不使用自己的数据上下文 正如已经建议的,您必须覆盖 ControlTemplate,以便控件的客户端可以使用 Content 属性来定义您想要托管的实际内容。然后您只需切换 ContentPresenter 的可见性即可。 要启用自定义,我建议创建一个扩展 HeaderedContentControl 的自定义控件,而不是使用 UserControl。 HeaderedContentControl 为您提供 Header 属性和 Content 属性 - 正是您想要的。 但是,因为已经有一个框架 Expander 控件(也扩展了 HeaderedContentControl),所以您应该扩展 Expander 并向现有控件添加其他功能: MyExpander.cs 每个控件绝不能依赖于其数据上下文。控件必须与数据上下文无关。如果您需要外部数据,则必须通过公共依赖属性请求它。内部元素将绑定到这些依赖属性以获取其数据。 这样,控件的客户端就可以完全控制 DataContext,并且能够通过数据绑定提供所需的数据 - 不会出现任何意外(例如,绑定失败,因为控件内部更改了 DataContext!)。 class MyExpander : Expander { static MyExpander() { // You can remove this if you only need to add behavioral functionality // but want to keep the original visuals and visual states. FrameworkElement.DefaultStyleKeyProperty.OverrideMetadata( typeof(MyExpander), new FrameworkPropertyMetadata(typeof(MyExpander))); } // TODO::Add new functionality to the existing Expander } Generic.xaml 示例模板。仅当从静态构造函数显式覆盖默认样式时才需要。您可以看到 ContentPresenter is collapsed or visible based on the Expander.IsExpanded` 属性如何: <Style TargetType="{x:Type local:ExportManagerDialogStyle}"> <Style.Resources> <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> </Style.Resources> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:ExportManagerDialogStyle}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition /> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Text="{TemplateBinding Header}" /> <ContenPresenter Grid.Row="1" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded, Converter={StaticResourtce BooleanToVisibilityConverter}}" /> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> MainWindow.xaml <Window> <!-- Either inherit or explicitly set the DataContext --> <MyExpander DataContext="{ExpanderViewModel}" Header="Expandable content" IsExpanded="True"> <ListBox /> </MyExpander>