XAML用户控件继承 [英] XAML UserControl inheritance

查看:251
本文介绍了XAML用户控件继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从Java来了,我真的用一种常见的做法,当涉及到使GUI组件:我平时做一些基础类的包含了所有常用的对象为我的GUI组件,然后我扩展它

Coming from Java, I'm really used to a common practice when it comes to make GUI components: I usually do some sort of base class which contains all the common objects for my GUI components and then I extend it.

所以,基本上,这是想什么,我实现了与C#和XAML。

So, basically, this is what I'd like to achieve with C# and XAML.

为了使问题清楚,这里是一个例子(不工作!)的我在做什么:

To make the question clear, here's an example (that is not working!) of what I'm doing:

我们已经有了它自己的XAML的基类

We've got a base class with its own XAML

<UserControl x:Class="BaseClass"
    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"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">

    <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">
        <Border BorderBrush="Aqua" BorderThickness="10" CornerRadius="10" x:Name="Border" HorizontalAlignment="Left" Height="480" VerticalAlignment="Top" Width="480"/>

    </Grid>
</UserControl>



然后,我们已经得到了延伸第一个

and then we've got a class which extends the first one

<base:BaseClass x:Class="DerivedClass"
    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:base="clr-namespace:BaseClass"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="60" d:DesignWidth="200">

    <Grid x:Name="LayoutRoot" Margin="0" Width="200" Height="60" MaxWidth="200" MaxHeight="60" Background="{StaticResource PhoneAccentBrush}">        
        <TextBlock x:Name="dummyText" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="Dummy Plugin" VerticalAlignment="Top" Height="40" Width="180" Foreground="White" TextAlignment="Center"/>
    </Grid>
</base:BaseClass>



从2 XAML代码,我想做些什么开始是让 DerivedClass 的BaseClass 容器。
这将让我分享各种派生类之间的组件,而无需编写代码,每次我需要它。

Starting from the 2 XAML codes, what I'd like to do is to have the DerivedClass into the BaseClass container. This will allow me to share components between the various derived classes without having to write the code everytime that I need it.

例如,如果我想所有我的组件有圆角的边框,我想只是把它在低音类,然后把它在所有派生的人而不必重写它。

For example, if I want all my components to have that rounded border, I'd like to just put it in the bass class and then have it in all the derived ones without having to rewrite it.

当然,每个C#类都有自己的的InitializeComponent()方法,这可能意味着派生的组件将建成通过去除基类一自己的内容。

Of course, each c# class has its own InitializeComponent() method and this probably means that the derived component will build its own content by removing the base class' one.

删除从 DerivedClass 构造方法让我即使在派生类中的基本内容,但是,当然,我输一切,我在 DerivedClass

Removing the method from the DerivedClass constructor gives me the base content even in the derived class, but, of course, I lose everything I made in the XAML design window of the DerivedClass.

调用从<$ C $基构造制成C> DerivedClass 没有任何影响,因为它被称为前衍生的InitializeComponent()

Calling the base constructor from the DerivedClass has no effect, as it's called before the derived InitializeComponent().

所以,问题是:我怎么能使用XAML设计从基类到派生一个没有打破派生类的XAML设计?有没有办法简单地将内容添加到基类,同时还与设计师本身的工作?

So the question is: how can I use the XAML design from a base class into the derived one without breaking the XAML design of the derived class? Is there any way to simply add content to the base class while still working with the designer itself?

(我知道我可以删除XAML派生类,做我想通过代码来完成,但我想知道如果我能做到这一点正好与设计师,因为我不想写我的GUI时,我有一个可用的设计师什么的)

(I know that I can remove the XAML for the derived class and do what I want to do by code, but I want to know if I can do this just with the designer as I don't want to write my GUI when I have a designer available)

编辑:

继HighCore的答复,我做了一些关于Windows Phone的作品,但我不知道,我做正确的事(是的, !它的工作原理,但也许是错误的)

Following HighCore's reply, I did something that works on Windows Phone but I'm not sure that I'm doing the right thing (yeah, it works, but maybe is just wrong!).

下面是我所做的:

BaseControl.xaml

BaseControl.xaml

<UserControl x:Class="TestInheritance.BaseControl"
    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"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">


     <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneChromeBrush}">        
        <TextBlock HorizontalAlignment="Center">BASE</TextBlock>        
        <ContentPresenter Name="Presenter" Content="{Binding PresenterContent}"/>
    </Grid>
</UserControl>



BaseControl.xaml.cs

BaseControl.xaml.cs

namespace TestInheritance
{
    public partial class BaseControl : UserControl
    {

        public Grid PresenterContent { get; set; }        

        public BaseControl()
        {
            DataContext = this;
            InitializeComponent();            
        }
    }
}



DerivedControl.xaml

DerivedControl.xaml

<local:BaseControl x:Class="TestInheritance.DerivedControl"
    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:TestInheritance"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    d:DesignHeight="480" d:DesignWidth="480">

    <local:BaseControl.PresenterContent>
        <Grid>
            <TextBlock VerticalAlignment="Bottom" HorizontalAlignment="Center">DERIVED</TextBlock>
        </Grid>
    </local:BaseControl.PresenterContent>
</local:BaseControl>

请注意, DerivedClass 是一个实例的的BaseClass ,因为我需要他们有其他原因一些常见的属性/方法。

Please note that the DerivedClass is an instance of BaseClass as I need them to have some common properties/methods for other reasons.

你觉得什么我的解决方案? ?是否有意义

What do you think about my solution? Does it make sense?

推荐答案

好吧,让我这个分成几部分:

Ok, let me split this into parts:

从Java即将

忘记java中。这是它自上世纪90年代还没有进化真的过时的语言。 C#是好上千万倍和WPF是最好的UI框架是最新的。

Forget java. It's a really antiquated language which has not evolved since the 90's. C# is a million times better and WPF is the best UI framework up to date.

这是我所看到的,Java的UI框架,如秋千概念上类似于。 Net的的WinForms,这也被换成了WPF。

from what I've seen, java UI frameworks such as swing are conceptually similar to .Net's winforms, which has also been replaced by WPF.

WPF(和它的基于XAML的弟兄)来自任何其他框架有着根本的不同各地由于它们的定制能力通过样式和模板和的数据绑定

WPF (and it's XAML-based brethren) are fundamentally different from any other frameworks around because of their enhanced capability for customization via Styles and Templates and support for DataBinding.

由于这个原因,一个的 的重大思维转变 是在WPF启动时需要。

Because of this, a Significant Mindshift is required when starting on WPF.

我通常做一些基础类的包含了所有常用的
对象为我的GUI组件,然后我对它进行扩展。

I usually do some sort of base class which contains all the common objects for my GUI components and then I extend it.

在WPF中,还有的内容模型 ,这消除了继承等臃肿unnecesary实践的需要,通过引入能力,把内的任何东西。

In WPF, there's the Content Model, which removes the need for inheritance and other bloated unnecesary practices, by introducing the capability to put "anything inside anything".

例如,一个按钮可以这样定义:

For example, a Button can be defined like this:

<Button>
    <Button.Content>
        <StackPanel Orientation="Horizontal">
            <Ellipse Fill="Red" Height="10" Width="10" Margin="2"/>
            <TextBlock Text="Click Me"/>
        </StackPanel>
    <Button.Content>
 </Button>



这将导致

which results in

有没有必要从巴顿刚刚继承定义它的内容。

There's no need to inherit from Button just to define it's content.

有一个附加的优点WPF提供,是非常方便的的 ContentProperty 属性定义什么XAML标记的内容<按钮> < /按钮> 表示。 按钮是的 ContentControl中 ,该声明是这样的:

There is an additional advantage WPF provides and is really handy, the ContentProperty Attribute which defines what the content of the XAML tags <Button> </Button> represents. Button is derived from ContentControl, which is declared like this:

//Declaration of the System.Windows.Control.ContentControl class,
//inside the PresentationFramework.dll assembly
//...  
[ContentProperty("Content")]
public class ContentControl: Control //...
{
   //...
}

这意味着下面的XAML是功能上等同于上面的:

This means that the following XAML is functionally identical to the above:

<Button>
   <StackPanel Orientation="Horizontal">
       <Ellipse Fill="Red" Height="10" Width="10" Margin="2"/>
       <TextBlock Text="Click Me"/>
    </StackPanel>
</Button>




  • 请注意,我们已经删除了<按钮.Content方式> 标签,因为 ContentProperty 属性需要的是照顾

    • Notice we have removed the <Button.Content> tag, because the ContentProperty attribute takes care of that.
    • 这一切成为可能得益于一个称为 CONTROLTEMPLATES ,该定义控件的外观,独立于它的行为。

      All this is made possible thanks to a feature called ControlTemplates, which define the Visual appearance of a Control, independently of it's behavior.

      我想要做的是有DerivedClass入的BaseClass
      容器

      what I'd like to do is to have the DerivedClass into the BaseClass container.

      有几种方法可以做到这一点,其中之一是利用 CONTROLTEMPLATES 和定义XAML内特定容器将承载的内容:

      There are several ways to achieve that, one of them is to leverage ControlTemplates and define a specific container inside the XAML that will host the content:

      <UserControl x:Class="BaseClass">
          <UserControl.Template>
              <ControlTemplate TargetType="UserControl">
                  <DockPanel>
                      <TextBlock DockPanel.Dock="Top" Text="I'm the Container"/>
      
                      <!-- This is where the Hosted Content will be placed -->
                      <ContentPresenter ContentSource="Content"/>
                  </DockPanel>
              </ControlTemplate>
           <UserControl.Template>
      </UserControl>
      



      然后,你可以重新使用这个模板是这样的:

      Then you could reuse this template like this:

      <Window>
         <my:BaseClass>
             <Border Background="Gray" BorderBrush="Blue" BorderThickness="2"
                     VerticalAlignment="Center" HorizontalAlignment="Center">
                 <TextBlock Text="Im the Hosted Content" Foreground="AliceBlue"/>
             </Border>
         </my:BaseClass>
      </Window>
      



      这会导致:

      which results in:

      无需继承或任何程序代码的东西。

      No need for inheritance or any procedural code stuff.

      另外一个很重要的方面在WPF中,这是在重大思维转变以上链接广泛解释启动时是什么,我告诉大家在这里:

      Another very important aspect when starting in WPF, which is extensively explained in the "Significant Mindshift" link above, is what I tell everyone here:

      了解MVVM你曾经编写的代码在WPF一行之前


      • 你们中的大多数不要放在WPF UI元素的任何代码,因为大部分的东西可以通过<实现时间code>数据绑定(包括在数据绑定链接以上),或通过实施可重复使用附加行为附属性的。只有查看特定代码应放置在后面的代码,这不处理数据或业务逻辑

      • Most of the time you don't put any code in WPF UI elements, because most things can be achieved by DataBinding (covered in the "DataBinding" link above), or by implementing Reusable Attached Behaviors or Attached Properties. Only VIEW-Specific code should be placed in code behind, which does not deal with Data or Business Logic

      您可能会在其他框架中被用来样板,如:

      The boilerplate you might be used to in other frameworks, such as:

      txtLastName.Text = person.LastName;
      txtFirstName.Text = person.FirstName;
      btnSubmit.IsEnabled = person.IsActive;
      



      之类的东西,在WPF中,又完全不必要的,因为数据绑定的。

      and stuff like that, is completely unneeded in WPF, again, because of DataBinding.

      另外一个概念,它实现了高灵活性,当涉及到显示的UI数据WPF的 的DataTemplates ,它允许你定义一个特定用户界面时,一些数据类型为呈现在屏幕上使用。

      Another concept which enables high flexibility when it comes to showing data in the UI is WPF's DataTemplates, which allow you to define a specific UI to be used when some Data Type is "rendered" on screen.

      由于上述所有的,WPF与大多数的UI框架有着根本的不同在那里,从而消除了所有可怕的样板和黑客这是常见于其他框架,

      Because of all of the above, WPF is fundamentally different from most UI frameworks out there, and thus removes the need for all the horrible boilerplate and hacks which are common in other frameworks,

      我建议你阅读的需要高达上定义应用程序的总体结构和UI时提供并记住所有这些概念和实践的各个环节。

      I suggest you read up on all the links provided and keep in mind all these concepts and practices when defining an application's structure and UI in general.

      让我知道如果你需要进一步的援助。

      Let me know if you need further assistance.

      这篇关于XAML用户控件继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆