我有一個定義用戶控制元件的基礎庫
BaseLib.dll:
UC.xaml.cs
<UserControl x:Class="BaseLib.UC" ...
UC.xaml.cs
public abstract partial class UC : UserControl, IFoo
{
public UC()
{
InitializeComponent();
}
protected abstract Foo();
}
然后,不同的庫可以從控制元件繼承并多載方法。它們只實作抽象方法,對底層 XAML 不做任何事情
Lib2.dll
public class NewControl : UC
{
protected override Foo(){ /* do stuff*/}
}
基本庫編譯得很好,派生類也是如此。但是,當我嘗試創建派生控制元件的實體時,我在 UC 建構式中的 InitializeComponent() 上收到此錯誤:
System.Exception: 'The component 'NewControl' does not have a resource identified by the URI '/BaseLib;component/UC.xaml'.'
這是我可以在某處使用pack URI修復以指向baselib xaml的東西嗎?我不知道我會把它放在哪里。我看過類似的問題,但它們并不完全符合我的意圖。我不想繼承 WPF 元素并更改它們的外觀或布局
uj5u.com熱心網友回復:
要創建擴展的基類UserControl,您必須遵循一些規則。
- 基型別不能是 a
partial class(具有 XAML 檔案)。 - 由于基類不允許有部分 XAML 類定義,因此基類不得呼叫
InitializeComponent(). - 擴展基類的派生非抽象型別必須是
partial class具有 XAML 類定義的。 - 此派生控制元件的 XAML 根元素必須是基類。
如果要重用實際視圖(XAML 定義),則必須將其定義為資源,例如ControlTemplate.
推薦的方法是擴展ContentControl而不是UserControl(參見下面的第二個示例)。與擴展相比,這種方法沒有任何限制UserControl。這是非常直接的,特別是如果您想在不覆寫默認外觀的情況下擴展功能。
解決方案 1:使用作為超類創建基UserControl類(不推薦)
BaseUserControl.cs
庫中使用的抽象基類。
public abstract class BaseUserControl : UserControl, IFoo
{
protected abstract void Foo();
}
App.xaml
的BaseUserControlTemplate定義。
<Application.Resources>
<ControlTemplate x:Key="BaseUserControlTemplate"
TargetType="BaseUserControl">
<TextBlock Text="Reusable view from template" />
</ControlTemplate>
</Application.Resources>
Library1UserControl.xaml.cs
的自定義庫實作BaseUserControl。
public partial class Library1UserControl : BaseUserControl
{
public Library1UserControl()
{
InitializeComponent();
}
protected override void Foo()
{}
}
Library1UserControl.xaml.cs
重用預定義
的視圖定義Library1UserControl(例如,在App.xaml中)BaseControlTemplate。
<BaseControl x:Class="Library1UserControl"
Template="{StaticResource BaseUserControlTemplate}" />
ContentControl解決方案 2:使用或作為超類創建基Control類(推薦)
In case you want to explicitly define the view as part of the base class, then let your base class extent ContentControl (or Control) and define the default Style in the Generic.xaml resources (the Generic.xaml file is located in the Themes folder of the control library).
This way, all derived classes will automatically inherit the default view (unless they explicitly override the default Style).
Extending ContentControl or Control is generally the recommended approach over using UserControl.
You should consider to extend ContentControl instead of UserControl.
BaseControl.cs
public abstract class BaseControl : Control, IFoo
{
static BaseControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(BaseControl), new FrameworkPropertyMetadata(typeof(BaseControl)));
}
protected abstract void Foo();
}
Generic.xaml
The Generic.xaml file is located in the Themes folder of the control library.
<ResourceDictionary>
<Style TargetType="BaseControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="BaseControl">
<TextBlock Text="Reusable view from template" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Library1Control.cs
The derived type automatically inherits the default Style (and ControlTemplate) that was defined in the base type.
public class Library1Control : BaseControl
{
public Library1Control()
{}
protected override void Foo()
{}
}
uj5u.com熱心網友回復:
所以我做了一個類似的專案結構來測驗。這作業正常。該行將xmlns:local="clr-namespace:PoopToTest"參考您的 BaseLib.dll 命名空間。
<Window
x:Class="PoopToTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:PoopToTest"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Grid>
<local:ActualControl>
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="50"
Text="Hello" />
</local:ActualControl>
</Grid>
</Window>
基類。
namespace PoopToTest
{
public abstract class BaseControl : UserControl
{
public BaseControl()
{
//InitializeComponent() is not in UserControl. Needed a place to break.
int x = int.MaxValue;
}
protected abstract void Foo();
}
}
執行。
namespace PoopToTest
{
public class ActualControl : BaseControl
{
/// <inheritdoc />
protected override void Foo()
{
//Do Stuff.
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/446086.html
