在WPF中继承自UserControl

34

我对WPF比较陌生,现在我遇到了一个从用户控件继承的问题。

我创建了一个用户控件,现在需要从该控件继承并添加一些额外的功能。

有没有人做过这样的事情?任何帮助将不胜感激。

谢谢。


2
关于WPF的解决方法,可以参考以下链接:http://svetoslavsavov.blogspot.gr/2009/09/user-control-inheritance-in-wpf.html。或者,您也可以在祖先中明确定义GUI,具体请参见http://support.microsoft.com/kb/957231。 - George Birbilis
6个回答

31

好的,你需要创建你的基础控件。

public abstract class BaseUserControl : UserControl{...}

然后在 XAML 文件中:

<Controls:BaseUserControl x:Class="Termo.Win.Controls.ChildControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:Namespace.Of.Your.BaseControl">

那应该可以工作。

编辑:嗯...这个例子在你有一个没有 XAML 的基础控件并从中继承时很有用。反过来(从带有 XAML 的基本控件)-我不确定您如何处理。

编辑2: 显然根据这篇文章+评论,我认为您想要的可能不可能实现。


3
就我所记得的,当你试图在XAML中继承一个抽象类时,设计师会抱怨。否则,这应该可以正常工作。 - Nikos Tsokos
1
这个不起作用。 - xoxox
2
外部帖子的链接已失效。 - StayOnTarget
你知道这个在WinUI 3中能否工作吗?我一直无法让它工作 :/ - Felix

18

这个链接似乎无法使用。(https://web.archive.org/web/20200815091447/http://geekswithblogs.net/lbugnion/archive/2007/03/02/107747.aspx[1]) - undefined

4
我可能有一个解决方案:组合而非继承 - 我想出了一种控件,它具有可以从外部通过数据绑定分配的“内容插槽”,请查看我的SO线程
使用示例:
<UserControl ... >

    <!-- My wrapping XAML -->
        <Common:DialogControl>
                <Common:DialogControl.Heading>
                        <!-- Slot for a string -->
                </Common:DialogControl.Heading>
                <Common:DialogControl.Control>
                        <!-- Concrete dialog's content goes here -->
                </Common:DialogControl.Control>
                <Common:DialogControl.Buttons>
                        <!-- Concrete dialog's buttons go here -->
                </Common:DialogControl.Buttons>
        </Common:DialogControl>
    <!-- /My wrapping XAML -->

</UserControl>

结合一些后端处理代码,它将成为对话框窗口的一个不错的基础组件。


3

您无法继承XAML代码本身。但是,创建一个代码后台的抽象类,将允许您从派生类对象中在代码后台进行编辑。

XAML代码:{ Window1.xaml }

<Window 
x:Class="WPFSamples.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="auto" Width="256" Title="WPF Sameples">
  <Grid>
    <Button x:Name="Button1" VerticalAlignment="Center" HorizontalAlignment="Center" Content="Click Me"/>
  </Grid>
</Window>

代码后端: { Window1.xaml.cs }

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFSamples
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public abstract partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
}

派生类: { DisabledButtonWindow.cs }

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WPFSamples
{
    public sealed class DisabledButtonWindow : Window1
    {
        public DisabledButtonWindow()
        {
            Button1.IsEnabled = false;
        }
    }
}

虽然你无法从wpf源代码中继承,但可以使用这个“Window1”控件作为所有其他派生控件的模板。

1

您可以使用delegate来实现此目的。

基本上,您需要创建一个接口(YourInterface),该接口封装了您想要的功能,然后使用户控件和您的类都实现该接口。

接下来,确保用户控件具有对类型为IYourInterface的对象的引用,以便当您的用户控件尝试调用Interface的方法时,它会调用您的类的方法。

因为用户控件和类都实现了相同的接口,所以它们可以被视为相同类型的对象-这意味着您可以将它们都放入类型为IYourInterface的对象集合中。这应该给您想要的行为。

在ASP.NET中,我经常使用这种技术,通过让我的类继承自abstract class祖先。我不明白为什么WPF不支持这一点。 :(


1
我认为你可以做到这一点,但是你需要重新定义在子类中引用的所有函数和可能的其他内容。例如,如果您在基类xaml中订阅了一个按钮单击事件,则需要在子类中重写按钮单击事件并调用基类按钮单击事件。由于我是从我的同事代码中获取信息,所以对细节不是百分之百确定,但我想这会给未来实现此功能的任何人一个起点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接