2017-02-09 4 views
0

Мне было бы хорошо с ответом в VB или C#, я знаю, что оба решения будут записаны в VB.Net. По сути, я хочу использовать шаблон для повторного использования зависимых свойств базы в n числах перестановок, но я отправлял xaml с кодом позади маршрута и оставил шаблон стиля. В основном я хочу сделать что-то подобное в пользовательский элемент управления, я хотел бы использовать для основы:Как вы наследуете зависимые свойства от базового пользовательского элемента управления WPF до нового пользовательского элемента управления, который наследуется?

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 

Что я хотел бы чтобы сделать что-то вроде этого:

Назначение1:

<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> 

Назначение2

<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 ALMOST ТОЧНО, как есть? Everytime я пытаюсь сделать «унаследована (baseclassname)» в коде позади, я получаю эту ошибку:

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

Так я вроде застрял царапать мою голову не достаточно знать, на языке и возможностей WPF это может быть сделано или должно быть сделано в этом отношении.

+1

Базовый класс не должен иметь какой-либо файл содержимое, ни XAML, так как это будет перекрываться полученными экземплярами UserControl. Хотите ли вы использовать сетку «PART_TestLayout» в производных элемента управления? – mm8

+0

Да, по большей части рисунок выполняется в коде позади, но я все еще привязываю элементы данных в традиционной архитектуре MVVM. Я хочу повторно использовать общие свойства Dependent, а не очень разборчивы. Я просто не хочу, чтобы они устанавливали их 2, 3 или 4 раза для разных итераций. – djangojazz

+0

@ mm8 Должно быть больше наследования с помощью пользовательского элемента управления XAML, наследующего от чего-либо. Каждый раз, когда я пытаюсь, я всегда получаю: «Базовый класс« BaseTest », указанный для класса« Тест », не может отличаться от базового класса« UserControl »одного из его других частичных типов.». Я могу заставить его наследовать сам UserControl или нет, поместите этот djangojazz

ответ

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.В.Б:

Public Class UserControl1 
    Inherits Test 

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

Это то, что я искал, и маршрут, в который я попал. Даже просто повторное использование моих зависимых свойств - огромная победа. – djangojazz

0

UserControls для композиции. Если вы хотите разумное наследование, вы должны использовать настраиваемые элементы управления.

http://wpftutorial.net/HowToCreateACustomControl.html

В вашем случае я бы наследовать от TextBlock и добавить свойство в BottomText зависимость к нему. Затем создайте его в Generic.xaml в значительной степени, как вы это сделали.

Смотрите также здесь разница между UserControls и пользовательских элементов управления (последняя модель была построена для случая использования): http://wpftutorial.net/CustomVsUserControl.html

+0

Проблема, с которой мне любопытно идти по этому маршруту, хотя, как правило, у вас есть что-то вроде этого в стиле: