gpt4 book ai didi

WPF:带有 2 个(或更多!)ContentPresenters 的模板或 UserControl 以在 'slots' 中呈现内容

转载 作者:行者123 更新时间:2023-12-03 10:39:40 25 4
gpt4 key购买 nike

我正在开发 LOB 应用程序,我需要多个对话框窗口(并且在一个窗口中显示所有内容不是一个选项/没有意义)。

我想为我的窗口提供一个用户控件,它可以定义一些样式等,并且会有 几个 可以插入内容的插槽 - 例如,模态对话框窗口的模板将有一个用于内容和按钮的插槽(以便用户可以提供内容和一组带有绑定(bind) ICommand 的按钮)。

我想要这样的东西(但这不起作用):

用户控件 xaml:

<UserControl x:Class="TkMVVMContainersSample.Services.Common.GUI.DialogControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
>
<DockPanel>
<DockPanel
LastChildFill="False"
HorizontalAlignment="Stretch"
DockPanel.Dock="Bottom">
<ContentPresenter ContentSource="{Binding Buttons}"/>
</DockPanel>
<Border
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
Padding="8"
>
<ContentPresenter ContentSource="{Binding Controls}"/>
</Border>
</DockPanel>
</UserControl>

这样的事情可能吗?我应该如何告诉 VS 我的控件公开了两个内容占位符,以便我可以这样使用它?
<Window ... DataContext="MyViewModel">

<gui:DialogControl>
<gui:DialogControl.Controls>
<!-- My dialog content - grid with textboxes etc...
inherits the Window's DC - DialogControl just passes it through -->
</gui:DialogControl.Controls>
<gui:DialogControl.Buttons>
<!-- My dialog's buttons with wiring, like
<Button Command="{Binding HelpCommand}">Help</Button>
<Button Command="{Binding CancelCommand}">Cancel</Button>
<Button Command="{Binding OKCommand}">OK</Button>
- they inherit DC from the Window, so the OKCommand binds to MyViewModel.OKCommand
-->
</gui:DialogControl.Buttons>
</gui:DialogControl>

</Window>

或者,也许我可以将 ControlTemplate 用于窗口 like here ,但话又说回来:窗口只有一个内容槽,因此它的模板将只能有一个演示者,但我需要两个(如果在这种情况下它可能可以使用一个,还有其他用例几个内容槽会出现,只需考虑文章的模板 - 控件的用户将提供标题、(结构化)内容、作者姓名、图像......)。

谢谢!

PS:如果我只想并排放置按钮,如何将多个控件(按钮)放到 StackPanel 中? ListBox 有 ItemsSource,但 StackPanel 没有,而且它的 Children 属性是只读的 - 所以这不起作用(在用户控件内):
<StackPanel 
Orientation="Horizontal"
Children="{Binding Buttons}"/>

编辑:我不想使用绑定(bind),因为我想将 DataContext(ViewModel)分配给整个窗口(等于 View),然后从插入控件“插槽”的按钮绑定(bind)到它的命令 - 所以任何使用层次结构中的绑定(bind)会破坏 View DC 的继承。

至于从 HeaderedContentControl 继承的想法——是的,在这种情况下它会起作用,但是如果我想要三个可替换的部分呢?如何制作自己的“HeaderedAndFooteredContentControl” (或者,如果我没有 HeaderedContentControl,我将如何实现) ?

EDIT2:好的,所以我的两个解决方案不起作用 - 这就是原因:
ContentPresenter 从 DataContext 获取它的内容,但我需要对包含的元素进行绑定(bind)以链接到原始窗口(逻辑树中 UserControl 的父级)DataContext - 因为这样,当我嵌入绑定(bind)到 ViewModel 属性的文本框时,它没有被绑定(bind),因为控件内部的继承链已经断了!

似乎我需要保存父级的 DataContext,并将其恢复到所有控件容器的子级,但我没有得到任何事件表明逻辑树中的 DataContext 已更改。

EDIT3:我有一个解决方案! ,删除了我之前的回答。
看我的回复。

最佳答案

好的,我的解决方案完全没有必要,这里是创建任何用户控件所需的唯一教程:

  • http://www.interact-sw.co.uk/iangblog/2007/02/14/wpfdefaulttemplate
  • http://www.codeproject.com/Articles/37326/Lookless-Controls-Themes.aspx
  • http://www.codeproject.com/Articles/35444/Defining-the-Default-Style-for-a-Lookless-Control.aspx
  • http://blog.pixelingene.com/?p=58

  • 简而言之:

    子类化一些合适的类(或 UIElement,如果不适合你) - 文件只是简单的 *.cs,因为我们只定义行为,而不是控件的外观。
    public class EnhancedItemsControl : ItemsControl

    为您的“插槽”添加依赖属性(普通属性不够好,因为它对绑定(bind)的支持有限)。很酷的技巧:在 VS 中,写 propdp并按 Tab 键展开代码段:):
    public object AlternativeContent
    {
    get { return (object)GetValue(AlternativeContentProperty); }
    set { SetValue(AlternativeContentProperty, value); }
    }

    // Using a DependencyProperty as the backing store for AlternativeContent. This enables animation, styling, binding, etc...
    public static readonly DependencyProperty AlternativeContentProperty =
    DependencyProperty.Register("AlternativeContent" /*name of property*/, typeof(object) /*type of property*/, typeof(EnhancedItemsControl) /*type of 'owner' - our control's class*/, new UIPropertyMetadata(null) /*default value for property*/);

    为设计器添加一个属性(因为您正在创建所谓的无外观控件),这样我们就说我们需要在我们的模板中有一个名为 PART_AlternativeContentPresenter 的 ContentPresenter
    [TemplatePart(Name = "PART_AlternativeContentPresenter", Type = typeof(ContentPresenter))]
    public class EnhancedItemsControl : ItemsControl

    提供一个静态构造函数,它将告诉 WPF 样式系统我们的类(没有它,将不会应用针对我们新类型的样式/模板):
    static EnhancedItemsControl()
    {
    DefaultStyleKeyProperty.OverrideMetadata(
    typeof(EnhancedItemsControl),
    new FrameworkPropertyMetadata(typeof(EnhancedItemsControl)));
    }

    如果你想对模板中的 ContentPresenter 做一些事情,你可以重写 OnApplyTemplate 方法:
    //remember that this may be called multiple times if user switches themes/templates!
    public override void OnApplyTemplate()
    {
    base.OnApplyTemplate(); //always do this

    //Obtain the content presenter:
    contentPresenter = base.GetTemplateChild("PART_AlternativeContentPresenter") as ContentPresenter;
    if (contentPresenter != null)
    {
    // now we know that we are lucky - designer didn't forget to put a ContentPresenter called PART_AlternativeContentPresenter into the template
    // do stuff here...
    }
    }

    提供默认模板:始终在 ProjectFolder/Themes/Generic.xaml 中(我有我的独立项目,其中包含所有自定义的通用 wpf 控件,然后从其他解决方案中引用)。这只是系统为您的控件查找模板的地方,因此将项目中所有控件的默认模板放在此处:
    在这个片段中,我定义了一个新的 ContentPresenter,它显示了我们的 AlternativeContent 的值。附属属性(property)。注意语法 - 我可以使用 Content="{Binding AlternativeContent, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WPFControls:EnhancedItemsControl}}}"Content="{TemplateBinding AlternativeContent}" ,但如果您在模板中定义模板(例如 ItemPresenters 的样式所必需的),则前者将起作用。
    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:WPFControls="clr-namespace:MyApp.WPFControls"
    >

    <!--EnhancedItemsControl-->
    <Style TargetType="{x:Type WPFControls:EnhancedItemsControl}">
    <Setter Property="Template">
    <Setter.Value>
    <ControlTemplate TargetType="{x:Type WPFControls:EnhancedItemsControl}">
    <ContentPresenter
    Name="PART_AlternativeContentPresenter"
    Content="{Binding AlternativeContent, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WPFControls:EnhancedItemsControl}}}"
    DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type WPFControls:EnhancedItemsControl}}}"
    />
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>

    </ResourceDictionary>

    瞧,您刚刚制作了您的第一个无外观 UserControl(为更多“内容槽”添加更多内容呈现器和依赖属性)。

    关于WPF:带有 2 个(或更多!)ContentPresenters 的模板或 UserControl 以在 'slots' 中呈现内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1029955/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com