2009-11-26 11 views
11

У меня много пользовательских элементов управления, как это:Каков наилучший способ повторного использования блоков XAML?

PageManageCustomers.xaml.cs:

public partial class PageManageCustomers : BasePage 
{ 
... 
} 

, которые наследуют:

PageBase.cs:

public class BasePage : UserControl, INotifyPropertyChanged 
{ 
... 
} 

С PageBase.c s имеет нет сопровождающего файла XAML, я должен поместить XAML, на который он ссылается в , каждый элементов управления пользователя, которые наследуют его, например. следующий блок повторяется в каждый XAML файл каждого элемента управления, который наследуется PageBase:

<DataTemplate x:Key="manageAreaCellTemplate"> 
    <StackPanel Orientation="Horizontal"> 
     <TextBlock Style="{DynamicResource ManageLinkStyle}" 
    Tag="{Binding Id}" Text="Delete" MouseDown="System_Delete_Click"/> 
     <TextBlock Text=" "/> 
     <TextBlock Style="{DynamicResource ManageLinkStyle}" 
      Tag="{Binding Id}" Text="Edit" MouseDown="System_Edit_Click"/> 
    </StackPanel> 
</DataTemplate> 

Я пытаюсь поставить этот блок в файл ресурсов, но не могу получить правильный синтаксис, он говорит :

'ResourceDictionary' корневой элемент требует топор: атрибут класса для обработчиков поддержки событий в файле XAML . Либо удалите обработчик событий для события MouseDown, либо добавьте атрибут x: Class к корневому элементу .

Или, возможно, я мог бы прочитать эти блоки с XamlReader `каким-то образом?

Как я могу поместить этот повторяющийся блок кода в одном месте, чтобы он не повторялся в каждом файле XAML, который наследует BagePage?

Вот воспроизводимость пример этой проблемы:

Window1.xaml:

<Window x:Class="TestXamlPage8283.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <StackPanel x:Name="MainContent"/> 
</Window> 

Window1.xaml.cs:

using System.Windows; 

namespace TestXamlPage8283 
{ 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 

      Page1 page1 = new Page1(); 
      MainContent.Children.Add(page1); 

      Page2 page2 = new Page2(); 
      MainContent.Children.Add(page2); 
     } 
    } 
} 

Page1.xaml :

<local:BasePage x:Class="TestXamlPage8283.Page1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:TestXamlPage8283" 
    Height="40" Width="300"> 
    <StackPanel> 
     <TextBlock Text="{Binding PageTitle}" 
        FontSize="14" 
        FontWeight="Bold"/> 
     <TextBlock Text="This is XAML that is specific to page one." /> 
    </StackPanel> 
</local:BasePage> 

Page1.xaml.cs:

namespace TestXamlPage8283 
{ 
    public partial class Page1 : BasePage 
    { 
     public Page1() 
     { 
      InitializeComponent(); 
      PageTitle = "Page One"; 
     } 
    } 
} 

Page2.xaml:

<local:BasePage x:Class="TestXamlPage8283.Page2" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:TestXamlPage8283" 
    Height="40" Width="300"> 
    <StackPanel> 
     <TextBlock Text="{Binding PageTitle}" 
        FontSize="14" 
        FontWeight="Bold"/> 
     <TextBlock Text="This is XAML that is specific to page two." /> 
    </StackPanel> 
</local:BasePage> 

Page2.xaml.CS:

namespace TestXamlPage8283 
{ 
    public partial class Page2 : BasePage 
    { 
     public Page2() 
     { 
      InitializeComponent(); 
      PageTitle = "Page Two"; 
     } 
    } 
} 

BasePage.cs:

using System.Windows.Controls; 
using System.ComponentModel; 

namespace TestXamlPage8283 
{ 
    public class BasePage : UserControl, INotifyPropertyChanged 
    { 
     #region ViewModelProperty: PageTitle 
     private string _pageTitle; 
     public string PageTitle 
     { 
      get 
      { 
       return _pageTitle; 
      } 

      set 
      { 
       _pageTitle = value; 
       OnPropertyChanged("PageTitle"); 
      } 
     } 
     #endregion 

     public BasePage() 
     { 
      DataContext = this; 
     } 

     #region INotifiedProperty Block 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected void OnPropertyChanged(string propertyName) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 

      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
     #endregion 
    } 
} 

Как принимать этот блок

<TextBlock Text="{Binding PageTitle}" 
      FontSize="14" 
      FontWeight="Bold"/> 

из из Page1.xa мл и Page2.xaml и поместите его в один место, чтобы я мог ссылаться на на него с Страница1.xaml и Page2.xaml? (так что, когда я хочу изменить FontSize = 14 до FontSize = 16, я просто изменить его в одном месте)

+0

Кажется, что вы просите что-то похожее на мастер-страницы Asp.net. Я не знаю, возможно ли это. Для вашего последнего образца TextBlock (изменение FontSize текстового блока PageTitle), не для каких стилей? –

ответ

5

Используйте словари ресурсов - добавить MyDictionary.xaml файл в проект, установив его Build Action на «страницу «:

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <DataTemplate x:Key="manageAreaCellTemplate"> 
     <StackPanel Orientation="Horizontal"> 
      <TextBlock Style="{DynamicResource ManageLinkStyle}" 
       Tag="{Binding Id}" Text="Delete" MouseDown="System_Delete_Click"/> 
      <TextBlock Text=" "/> 
      <TextBlock Style="{DynamicResource ManageLinkStyle}" 
       Tag="{Binding Id}" Text="Edit" MouseDown="System_Edit_Click"/> 
     </StackPanel> 
    </DataTemplate> 
</ResourceDictionary> 

Затем в других файлах XAML вы обратитесь к нему:

<ResourceDictionary> 
    <ResourceDictionary.MergedDictionaries> 
     <ResourceDictionary Source="MyDictionary.xaml"/> 
    </ResourceDictionary.MergedDictionaries> 
    ... some other local resources ... 
</ResourceDictionary> 

и обратитесь к ресурсу, как Template={StaticResource manageAreaCellTemplate}.

+0

Когда я это делаю, он говорит мне: «Корневому элементу« ResourceDictionary »требуется атрибут ax: Class для поддержки обработчиков событий в файле XAML. Либо удалить обработчик событий для события MouseDown, либо добавить атрибут ax: Class в корневой элемент. " когда я добавляю атрибут x: Class, я получаю такие ошибки: «Отсутствует частичный модификатор при объявлении типа« TestApp.Pages.BasePageManageItems », существует еще одно частичное объявление этого типа» –

+1

Правильно, у вас есть события MouseDown, которые не могут быть связанными во время компиляции, поскольку словарь не имеет кода. Вы должны либо добавить обработчики событий во время выполнения, либо использовать команды: http://msdn.microsoft.com/en-us/library/ms752308.aspx. – Mart

Смежные вопросы