【发布时间】:2019-07-29 14:04:38
【问题描述】:
希望加载 XAML/事件/连接到 DLL 的用户控件的所有内容,该 DLL 在运行时加载到基于配置文件的另一个 WPF 项目中。
所以你有 2 个 DLL,只有一个会根据 JSON 配置加载,但是我希望我的所有按钮和一切都能正常工作。这是我有 ATM 的代码
Gray DLL 的用户控件
<UserControl x:Class="WPFGreyButtonTest.InstrumentUserControl"
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:WPFGreyButtonTest"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Label x:Name="colourName" Content="GREY" HorizontalAlignment="Left" Height="93" Margin="284,88,0,0" VerticalAlignment="Top" Width="243" FontWeight="Bold" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="50" Foreground="#FF8B8B8B"/>
</Grid>
</UserControl>
没有实际代码
Purple DLL 的用户控件
<UserControl x:Class="WPFPurpleButtonTest.InstrumentUserControl"
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:WPFPurpleButtonTest"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Label x:Name="colourName" Content="PURPLE" HorizontalAlignment="Left" Height="93" Margin="284,88,0,0" VerticalAlignment="Top" Width="243" FontWeight="Bold" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontSize="50" Foreground="#FFDC00FF"/>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="365,253,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</UserControl>
相关代码(两个 DLL 具有相同的类名,即 InstrumentUserControl)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WPFPurpleButtonTest
{
/// <summary>
/// Interaction logic for InstrumentUserControl.xaml
/// </summary>
public partial class InstrumentUserControl : UserControl
{
public static readonly DependencyProperty InnerButtonProperty = DependencyProperty.Register("InnerButton", typeof(Button), typeof(InstrumentUserControl));
public Button InnerButton
{
get { return (Button)GetValue(InnerButtonProperty); }
set { SetValue(InnerButtonProperty, value); }
}
public InstrumentUserControl()
{
InitializeComponent();
InnerButton = button;
}
}
}
主要 WPF 应用程序代码
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WPFSandBox
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
UserControl userControl = null;
InstrumentEnum instrumentType = InstrumentEnum.Invalid;
string dllToLoad = null;
// When we first initialize our WPF app, in the constructor we can
// allow a config file (such as a json) to be read and load up
// an appropriate user control view
public MainWindow()
{
InitializeComponent();
ReadJson();
LoadRunTimeDLL();
//var ucs = new List<InstrumentUserControl>();
var ucs = new List<UserControl>();
ucs.Add(userControl);
//ucs.Add(new UserControl1());
//ucs.Add(new UserControl1());
//ucs.Add(new UserControl1());
ic.ItemsSource = ucs;
}
private void ReadJson()
{
using (StreamReader r = new StreamReader("../../Config/Config.json"))
{
string json = r.ReadToEnd();
var jsonData = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
foreach (var entry in jsonData)
{
if (entry.Key == "InstrumentType")
{
Enum.TryParse(entry.Value, out instrumentType);
}
else if (entry.Key == "DllToLoad")
{
dllToLoad = entry.Value;
}
}
}
}
private void LoadRunTimeDLL()
{
string assemblyName = string.Format("{0}\\{1}.dll",
new FileInfo(Assembly.GetExecutingAssembly().Location).DirectoryName, dllToLoad);
if (assemblyName != null)
{
Assembly asm = Assembly.LoadFile(assemblyName);
Type[] tlist = asm.GetTypes();
foreach (Type t in tlist)
{
if (t.Name == "InstrumentUserControl")
{
userControl = Activator.CreateInstance(t) as UserControl;
break;
}
}
if (userControl != null)
{
//contentControl.Content = userControl;
}
}
}
}
}
它是 MainWindow xaml
<Window x:Class="WPFSandBox.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFSandBox"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<!--<Grid>
<ContentControl Grid.Row="1" x:Name="contentControl" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
</Grid>-->
<ItemsControl x:Name="ic" />
</Window>
如果我能确保无论哪个 DLL 被加载,按钮都能正常工作,任何帮助都将不胜感激。
我正在尝试在运行时加载 WPF DLL。工作正常,但按钮和事件绑定到主 WPF 应用程序是我不知道该怎么做
【问题讨论】:
-
你有什么问题? (我没有投反对票,但我猜其他人也基于同样的问题投了反对票)
-
是的(悲伤的时候:()。我试图在运行时加载 WPF DLL。工作正常,但按钮和事件与主 WPF 应用程序相关联是我不知道的怎么办
-
在一个不相关的说明中,您可能会考虑让您的所有仪器控件从某个基类扩展,以便您的主类可以有一些常见的方式与加载的任何内容进行交互,以及在搜索加载的内容时DLL 为所需的类型,您可以搜索从该基类扩展的类型(只是为了更具体,而不是搜索具有该名称的任何内容)。
-
如果有共同的事件,一个基类会解决这个问题。这样,所有按钮都会引发基类事件,您的主应用程序可以简单地订阅这些常见事件。否则,您将不得不使用一些反射来查找事件并订阅它们。
-
jhilgeman 您能否为您刚才所说的内容提供一个示例 + 可能对最初的问题有所帮助?