是否可以在WPF中從xmlns-packages(命名空間)的加載位置定義一個自定義區域。我的目標是定義喜歡的東西:鉤入wpf xmlns命名空間導入
xmlns:customUI="db-ui:IronPythonControl"
,這樣我可以從數據庫中加載我的控制,並用它在XAML這樣的:
<IronPythonControl x:Name="..." ... />
謝謝!
是否可以在WPF中從xmlns-packages(命名空間)的加載位置定義一個自定義區域。我的目標是定義喜歡的東西:鉤入wpf xmlns命名空間導入
xmlns:customUI="db-ui:IronPythonControl"
,這樣我可以從數據庫中加載我的控制,並用它在XAML這樣的:
<IronPythonControl x:Name="..." ... />
謝謝!
我相信你可以用MarkupExtension很好地解決這個問題。
我根據this guide生成了以下psueocode。
最終目標是這樣的。
<ContentControl Content="{ipc:IronPythonControl IronTextBox}"/>
我們定義標記擴展爲這樣:
namespace IronPythonControlsExample {
public class IronPythonControl : MarkupExtension
{
public string Name { get; private set;}
public IronPythonControl(string name)
{
Name = name;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (!string.IsNullOrEmpty(Name))
{
return LoadControl(Name);
}
}
public FrameworkElement LoadControl(string name){/*Load XAML Control from database here*/}
}
}
關鍵零部件這裏是我們擴展的MarkupExtension,並覆蓋ProvideValue。在ProvideValue中,我們驗證我們的狀態信息並加載控件。
在LoadControl中,您將放置代碼以從數據庫加載XAML,將其從Xaml轉換爲對象,然後將RootObject作爲結果返回。
您最終可能會使用比FrameworkElement更高或更低級別的控件。
現在我們已經定義了裝載機的擴展,我們可以在我們的項目
<Window x:Class="IronPythonControlsExample.IronPythonWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ipc="clr-namespace:IronPythonControlsExample"
Title="IronWindow" Height="300" Width="300">
<ContentControl Content="{ipc:IronPythonControl IronTextBox}"/>
</Window>
使用它雖然這是不掛鉤到命名空間聲明,它將允許你動態地加載和注入數據驅動的控制。
一個非常相似,但另一種方法是定義一個CustomControl和基它關閉ContentControl中的,在這個例子中,我們將使用.NET 4.0 x:Arguments directive以簡化代碼:
public class IronPythonControl : ContentControl
{
public IronPythonControl(string name)
{
Debug.Assert(!string.IsNullOrEmpty(name), "No name provided for control");
Content = LoadControl(name);
}
public FrameworkElement LoadControl(string name){/*Load XAML Control from database here*/}
}
在使用我們的結果會是這樣的:
<Window x:Class="IronPythonControlsExample.IronPythonWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ipc="clr-namespace:IronPythonControlsExample"
Title="IronWindow" Height="300" Width="300">
<ipc:IronPythonControl>
<x:Arguments>
<x:String>IronTextBox</x:String>
</x:Arguments>
</ipc:IronPythonControl>
</Window>
另一個好方法是非常相似,這CustomControl。然而,不要在構造函數中使用參數,我們可以定義一個PropertyChangedCallback。
public class IronPythonControl : ContentControl
{
public static readonly DependencyProperty ControlNameProperty =
DependencyProperty.Register("ControlName", typeof(string), typeof(IronPythonControl), new FrameworkPropertyMetadata("IronTextBlock", ControlNameChangedCallback));
private static void ControlNameChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
Content = LoadControl(ControlName);
}
public string ControlName
{
get { return (string)GetValue(ControlNameProperty); }
set { SetValue(ControlNameProperty, value); }
}
public FrameworkElement LoadControl(string name){/*Load XAML Control from database here*/}
}
而對於這種情況下一個XAML例如:
<ipc:IronPythonControl ControlName="IronTextBox"/>
</Window>
這些例子應該提供一個良好的解決方案,將加載XAML在UI加載時間,可以控制任何一個。
請注意,基於Ctor的方法和MarkupExtension不是動態的,如果您不希望控件在運行時更改,那麼這很好。
理論上,PropertyChanged方法將允許您更改控件名稱並根據新名稱動態地重新載入新內容。如果將ControlName綁定到TextBox並將其綁定UpdateSourceTrigger設置爲PropertyChanged,則可能很容易失控。
你也可以參考這些SO文章的更多細節: http://stackoverflow.com/questions/910814/loading-xaml-at-runtime –
我認爲你最後的解決方案符合我的概念。我會嘗試。非常感謝您的詳細解答! – BendEg
您的目標是動態加載並顯示XAML代碼? –
我已經動態加載並顯示帶有Ironpython的XAML代碼。現在我想加載其他動態控件的動態控件。例如,我使用XAML和IronPython創建了一個自定義文本框,並希望將它用於帶有XAML和ironPython的自定義窗口中。 – BendEg