如何从基础WPF用户控件继承从属属性到继承的新用户控件?

时间:2017-02-09 16:05:23

标签: c# wpf vb.net inheritance

我对VB或C#的回答很好,我知道两者,终极解决方案将用VB.Net编写。基本上我想使用一个模板在n个排列中重用基础的依赖属性,但是我在路径后面的代码中放弃了一个xaml并放弃了一个Style模板。基本上我想在用户控件中做这样的事情,我想用于基础:

XAML:

<UserControl x:Class="Test"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPFControls"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid Name="PART_TestLayout">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TextBlock Text="{Binding TestTitle}" Height="30" Background="White" Foreground="Black" />
    <TextBlock Name="PART_Text2" Grid.Row="1" Background="White" />
  </Grid>
</UserControl>

XAML背后的代码:

Imports System.ComponentModel

Public Class Test


  Public Sub New()
    InitializeComponent()
    PART_TestLayout.DataContext = Me
  End Sub

  Public Shared ReadOnly TestTitleProperty As DependencyProperty = DependencyProperty.Register("TestTitle", GetType(String), GetType(Test), New UIPropertyMetadata(String.Empty, AddressOf TestChanged))

  Public Property TestTitle As String
    Get
      Return CType(GetValue(TestTitleProperty), String)
    End Get
    Set
      SetValue(TestTitleProperty, Value)
    End Set
  End Property

  Private Shared Sub TestChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
    Dim m = DirectCast(d, Test)
    m.PART_Text2.Text = $"Changed {DateTime.Now.ToLongTimeString}"
  End Sub
  Public MustOverride Sub DoThing()
End Class

我想做的是这样的事情:

USE1:

<local:Test x:Class="TestInheritance"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPFControls"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
    <Label Content="I am the first implentation"/>
    <local:Test TestTitle="{Binding TestText}" />
  </Grid>
</local:Test>

USE2

<local:Test x:Class="TestInheritance2"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPFControls"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
    <Label Content="I am the second implentation"/>
    <local:Test TestTitle="{Binding TestText}" />
  </Grid>
</local:Test>

现在我知道我可以做这样的事情(可能就是我应该去的方式)

<UserControl x:Class="TestInheritance"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPFControls"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
    <local:Part1 TestTitle="{Binding TestText}" />
    <!-- myproprietaryContent -->
    <local:Part2 TestLegend="{Binding TestText2}" />
  </Grid>
</local:Test>

但我宁愿继承基础模板,只需应用我需要的一切。 我是否需要使用样式模板来执行此操作,还是可以按原样重复使用XAML UserControl?每次我尝试继承(baseclassname)&#39;在后面的代码我得到这个错误:

'Base class 'Test' specified for class 'TestInheritance' cannot be different from the base class 'UserControl' of one of its other partial types.'

所以我有点不知所措,对WPF的语言和功能了解不足,可以做到这一点,或者应该做到这一点。

2 个答案:

答案 0 :(得分:1)

您无法重复使用基础UserControl的内容,因为内容将被派生控件覆盖。基类应该只定义依赖项属性,并且没有任何XAML标记。

请参阅以下示例代码:

Test.vb(基类):

Public MustInherit Class Test
    Inherits UserControl

    Public Shared ReadOnly TestTitleProperty As DependencyProperty = DependencyProperty.Register("TestTitle", GetType(String), GetType(Test), New UIPropertyMetadata(String.Empty, AddressOf TestChanged))

    Public Property TestTitle As String
        Get
            Return CType(GetValue(TestTitleProperty), String)
        End Get
        Set
            SetValue(TestTitleProperty, Value)
        End Set
    End Property

    Private Shared Sub TestChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
        '...
    End Sub
    Public MustOverride Sub DoThing()
End Class

<强> UserControl1.xaml:

<local:Test x:Class="UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApplicationVb1"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>

    </Grid>
</local:Test>

<强> UserControl1.xaml.vb:

Public Class UserControl1
    Inherits Test

    Public Overrides Sub DoThing()
        '...
    End Sub
End Class

答案 1 :(得分:0)

UserControls用于构图。如果你想要合理的继承,你应该使用自定义控件。

http://wpftutorial.net/HowToCreateACustomControl.html

在您的情况下,我将从TextBlock继承并向其添加BottomText依赖项属性。然后在Generic.xaml中对其进行样式处理,就像你所做的那样。

另请参阅此处了解UserControls和自定义控件之间的区别(后一种模式是为您的用例构建的):http://wpftutorial.net/CustomVsUserControl.html

相关问题