WPF 自定义泛型用户控件后跨程序集继承用户控件的解决方案
自定义泛型用户控件:
<UserControl x:Class="ClassLibrary1.UcEumCmb" 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:ClassLibrary1" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Grid DataContext="{Binding ElementName=parent}"> <ComboBox Name="cmb2" SelectedItem="{Binding SelectedEnumValue}" /> </Grid> </UserControl>
public abstract partial class UcEumCmb : UserControl { } /// <summary> /// UcEumCmb.xaml 的交互逻辑 /// </summary> public class UcEumCmb<T> : UcEumCmb where T : struct { public UcEumCmb() { InitializeComponent(); // this.LoadViewFromUri("/ClassLibrary1;component/UcEumCmb.xaml"); foreach (Enum enumValue in Enum.GetValues(typeof(T))) { cmb2.Items.Add(enumValue); } } public T SelectedEnumValue { get { return (T)GetValue(SelectedEnumValueProperty); } set { SetValue(SelectedEnumValueProperty, value); } } public static readonly DependencyProperty SelectedEnumValueProperty = DependencyProperty.Register("SelectedEnumValue", typeof(T), typeof(UcEumCmb<T>), new FrameworkPropertyMetadata { BindsTwoWayByDefault = true }); }
然后声明一个用户控件类,继承即可
public class DayOfWeekSelectorExt2 : UcEumCmb<DayOfWeek> { }
以上参考了:
https://stackoverflow.com/questions/3811179/wpf-usercontrol-with-generic-code-behind
但是,当我们需要自定义泛型T用户控件的时候,大部分情况就是为了分离泛型T类库和用户控件类库之间的依赖,所以一般
DayOfWeekSelectorExt2 : UcEumCmb<DayOfWeek>
会放在主程序里去做
但是这会导致vs编辑器报错提示
不具有由 URI“/ClassLibrary1;component/uceumcmb.xaml”识别的资源。
直接运行也会报错
根据相关资料
1 https://blog.csdn.net/lishuangquan1987/article/details/123347719 (Wpf BUG:组件“XXX”不具有由 URI“XXX“识别的资源)
2 https://www.cnblogs.com/lindexi/p/16714348.html (dotnet 读 WPF 源代码笔记 为什么自定义的 UserControl 用户控件不能跨程序集继承)
3 https://stackoverflow.com/questions/7646331/the-component-does-not-have-a-resource-identified-by-the-uri
需要手动去load usercontrol对应的xaml解决方案如下:
public static class Extensions { public static void LoadViewFromUri(this FrameworkElement userControl, string baseUri) { try { var resourceLocater = new Uri(baseUri, UriKind.Relative); var exprCa = (PackagePart)typeof(Application).GetMethod("GetResourceOrContentPart", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { resourceLocater }); var stream = exprCa.GetStream(); var uri = new Uri((Uri)typeof(BaseUriHelper).GetProperty("PackAppBaseUri", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null, null), resourceLocater); var parserContext = new ParserContext { BaseUri = uri }; typeof(XamlReader).GetMethod("LoadBaml", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, new object[] { stream, parserContext, userControl, true }); } catch (Exception) { //log } } }
public UcEumCmb() { //InitializeComponent(); this.LoadViewFromUri("/ClassLibrary1;component/UcEumCmb.xaml"); foreach (Enum enumValue in Enum.GetValues(typeof(T))) { cmb2.Items.Add(enumValue); } }
取消 InitializeComponent,改为手动load
项目编译运行均正常,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <StackPanel Grid.Row= "1" VerticalAlignment= "Center" HorizontalAlignment= "Center" > <TextBlock Text= "{Binding DayOfWeek,StringFormat=You have selected {0}!}" /> <uc:DayOfWeekSelectorExt2 SelectedEnumValue= "{Binding DayOfWeek}" Margin= "0,5,0,0" /> <local:DayOfWeekSelectorExt3 SelectedEnumValue= "{Binding DayOfWeek}" Margin= "0,5,0,0" /> </StackPanel> using ClassLibrary1; namespace EnumSelector { public class SomeViewModel // TODO implement INotifyPropertyChanged to support all binding scenarios { public DayOfWeek DayOfWeek { get ; set ; } } public class DayOfWeekSelector : EnumComboBox<DayOfWeek> { } public class DayOfWeekSelectorExt : UserControl1<DayOfWeek> { } public class DayOfWeekSelectorExt3 : ClassLibrary1.UcEumCmb<DayOfWeek> { |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗