2016-09-05 12 views
3

xamlの定義を再利用することで、この質問を再現しました。私のプロジェクトでxaml名前空間の定義を再利用する方法

using System.Windows.Controls; 

namespace XamlDemo.Bar 
{ 
    public class ExtButton : Button { } 
    public class ExtLabel : Label { } 
} 
namespace XamlDemo.Foo 
{ 
    public class ExtTextBlock : TextBlock { } 
    public class ExtTextBox : TextBox { } 
} 

<UserControl x:Class="XamlDemo.ControlA" 
      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:XamlDemo" 
      xmlns:foo="clr-namespace:XamlDemo.Foo" 
      xmlns:bar="clr-namespace:XamlDemo.Bar" 
      mc:Ignorable="d"> 
<!-- 
    xmlns:foo="clr-namespace:XamlDemo.Foo" 
    xmlns:bar="clr-namespace:XamlDemo.Bar" 
    foo and bar will tend to repeat in exactly this constellation all over the project. 
    If one of these namespaces changes all xaml files need to be edited. 
    I would like to include a different file as a component where i would only write foo and bar once 
--> 
    <StackPanel> 
     <foo:ExtTextBlock></foo:ExtTextBlock> 
     <bar:ExtLabel></bar:ExtLabel> 
    </StackPanel> 
</UserControl> 


<UserControl x:Class="XamlDemo.ControlB" 
      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:XamlDemo" 
      xmlns:foo="clr-namespace:XamlDemo.Foo" 
      xmlns:bar="clr-namespace:XamlDemo.Bar" 
      mc:Ignorable="d" > 
    <StackPanel> 
     <foo:ExtTextBox></foo:ExtTextBox> 
     <bar:ExtButton></bar:ExtButton> 
    </StackPanel> 
</UserControl> 

どちらも私の地元の名前空間宣言を使用します。代わりに別のxamlへの参照を入れて、そこから名前空間を取得したいと思います。

私はこれを行う方法を見つけませんでした。これは、このように見えると思われるものを示すコンセプトコードです。明らかにこれはコンパイルされません。

<magic 
      xmlns:foo="clr-namespace:XamlDemo.Foo" 
      xmlns:bar="clr-namespace:XamlDemo.Bar"> 
</magic> 

<UserControl x:Class="..." 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns="get it from magic"> 
</UserControl> 
+0

XAML名前空間は何らかの形で特別ですか?通常のXMLルールに従っている場合、これらの名前空間宣言をユーザーコントロールの* containing要素に置くことができます(たとえば、両方の最も近い共通祖先を見つけるなど)。後で明示的に参照する必要はありません。 –

答えて

1

Freemanで述べたように、XAMLの継承は不可能です。とにかく、XmlnsDefinitionAttributeを使用して名前空間の定義を減らしたり消去したりすることができます。

CodeProjectで興味深い記事hereが見つかります。

XAML に含める名前空間が参照アセンブリにある場合は、簡単に単一のURIにマップできます。参照先のアセンブリに、このようにして属性を追加してください:

[assembly: XmlnsDefinition("urn:johannes-ui-controls", "XamlDemo.Foo")] 
[assembly: XmlnsDefinition("urn:johannes-ui-controls", "XamlDemo.Bar")] 

などです。

は、その後、あなたのXAMLで、あなたがこの方法でそれらを使用することができます。

<UserControl x:Class="..." 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:uiControls="urn:johannes-ui-controls"> 
    <StackPanel> 
     <uiControls:ExtTextBox /> 
     <uiControls:ExtButton /> 
    </StackPanel> 
</UserControl> 

この解決策の制限は、あなたのXAMLを含むアセンブリとXmlnsDefinition属性を使用することができないということです。 おそらく、これはあなたが意味するものではありませんが、おそらくそれはあなたを助けることができます。

1

ベース制御:

namespace WpfApplication9 
{ 
    public class BaseControl : UserControl 
    { 
     public BaseControl() 
     { 

     } 
    public override void EndInit() 
    { 
     base.EndInit(); 
     ExtTextBlock block = new ExtTextBlock { Width = 100 , Height = 20 , Text = "Test Block" }; 
     ExtButton button = new ExtButton { Width = 100, Height = 20 , Content = "ClickMe"}; 
     ExtLabel label = new ExtLabel { Width = 100, Height = 30 ,Content = "Test Label"}; 
     ExtTextBox txtBox = new ExtTextBox { Width = 100, Height = 20 ,Text= "Hi There"}; 
     Grid g = (Grid)BaseControl.FindChild(this, "gridMain"); 
     g.Children.Add(button); 
     g.Children.Add(block); 
     g.Children.Add(label); 
     g.Children.Add(txtBox); 
     Grid.SetRow(block, 0); 
     Grid.SetRow(button, 1); 
     Grid.SetRow(label, 2); 
     Grid.SetRow(txtBox, 3); 

     button.Click += button_Click; 
    } 

    void button_Click(object sender, RoutedEventArgs e) 
    { 
     MessageBox.Show("Hi There"); 
    } 

    public static DependencyObject FindChild(DependencyObject parent, string name) 
    { 
     // confirm parent and name are valid. 
     if (parent == null || string.IsNullOrEmpty(name)) return null; 

     if (parent is FrameworkElement && (parent as FrameworkElement).Name == name) return parent; 

     DependencyObject result = null; 

     if (parent is FrameworkElement) (parent as FrameworkElement).ApplyTemplate(); 

     int childrenCount = VisualTreeHelper.GetChildrenCount(parent); 
     for (int i = 0; i < childrenCount; i++) 
     { 
      var child = VisualTreeHelper.GetChild(parent, i); 
      result = FindChild(child, name); 
      if (result != null) break; 
     } 

     return result; 
    } 

    /// <summary> 
    /// Looks for a child control within a parent by type 
    /// </summary> 
    public static T FindChild<T>(DependencyObject parent) 
     where T : DependencyObject 
    { 
     // confirm parent is valid. 
     if (parent == null) return null; 
     if (parent is T) return parent as T; 

     DependencyObject foundChild = null; 

     if (parent is FrameworkElement) (parent as FrameworkElement).ApplyTemplate(); 

     int childrenCount = VisualTreeHelper.GetChildrenCount(parent); 
     for (int i = 0; i < childrenCount; i++) 
     { 
      var child = VisualTreeHelper.GetChild(parent, i); 
      foundChild = FindChild<T>(child); 
      if (foundChild != null) break; 
     } 

     return foundChild as T; 
    } 
} 
} 

namespace WpfApplication9.Foo 
{ 
    public class ExtTextBlock : TextBlock { } 
    public class ExtTextBox : TextBox { } 
} 

namespace WpfApplication9.Bar 
{ 
    public class ExtButton : Button { } 
    public class ExtLabel : Label { } 
} 

コントロール1. XAML

<base:BaseControl x:Class="WpfApplication9.Control1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:base="clr-namespace:WpfApplication9" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300"> 
<Grid x:Name="gridMain"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="1*"/> 
     <RowDefinition Height="1*"/> 
     <RowDefinition Height="1*"/> 
     <RowDefinition Height="1*"/> 
    </Grid.RowDefinitions> 
</Grid> 

あなたがコントロール1を作成するとあなたはControl2のクラスを作成することができます。 私が言ったように、xamlの無害は不可能です。

+0

応答のおかげで、私は明確にするために質問を編集しました。私はあなたの回答をどのように働かせるかわかりません。私の質問は不明であったかもしれません。もう少し詳しく説明できますか? – Johannes

+0

ああ、そうだ。したがって、コードの背後の部分でこれを本質的に解決します。正確には私が望んでいたものではありませんが、依存関係の名前を簡単に変更できます。 – Johannes

関連する問題