C# WPF 在运行时从 DLL 加载和使用自定义控件

C# WPF load and use custom controls from DLL during runtime

我是 WPF 的新手,也不是 C# 的专家,但是,我正在创建一个应用程序,它必须获得一组 true/false 状态并为每个状态创建切换开关,然后设置它的 (isChecked) 属性.

然而,在谷歌搜索大约 3 小时后,我找到了这段代码,这样我就可以在 运行 期间在 WPF 中使用外部控件,并将其编辑为控件,而不是切换开关:-

            Control Switch = null;
            Assembly asm = Assembly.LoadFile(Directory.GetCurrentDirectory() + "/CTS.dll");
            Type[] tlist = asm.GetTypes();
            foreach (Type t in tlist)
            {
                if (t.Name == "HorizontalToggleSwitch")
                {
                    Switch = Activator.CreateInstance(t) as Control;
                    break;
                }
            }

            Switch.Name = "MasterSwich" + i;
            Switch.HorizontalAlignment = HorizontalAlignment.Right;
            Switch.Margin = new Thickness(0, 0, 35, 0);
            Switch.Width = 100;
            Switch.Height = 35;

            SwichesPanel.Children.Add(Switch);

效果很好,但我无法设置任何与拨动开关相关的 属性(如 IsChecked),因为它仅将其视为控件。

我该如何解决这个问题,或者是否有更好的办法在 运行 时间内从 DLL 文件导入控件?

可以在这里找到切换开关文件以备不时之需:Toggle Switch Demo


更新:-

我可以在添加 Using ToggleSwitch; 时声明 HorizontalToggleSwitch 但我收到一个很好的错误提示

System.IO.FileNotFoundException: 'Could not load file or assembly 'ToggleSwitch, Version=1.1.0.0, Culture=neutral, PublicKeyToken=8637099990568f75' or one of its dependencies. The system cannot find the file specified.'

有什么想法吗?

我解决了,我只是导入了 更新 中提到的库,并使用进程管理器找出编译器在寻找什么,并发现它需要一个确切的DLL 的文件名,因此只需重新设置所有内容即可。

以防万一有人遇到同样的问题!这是我的解决方案。 我不知道为什么 Windows 正在为此苦苦挣扎,但是如果您仅在 xaml 中使用程序集,Windows 找不到它,或者在错误的文件夹中搜索。在我的例子中,我在 AddIn-Folder 中工作,not

System.AppDomain.CurrentDomain.BaseDirectory;

Addin aka Windows 在 C# 代码中使用时能够找到所有程序集,但是当我仅在 xaml 代码中使用 ToggleSwitch UI 元素时,它正在搜索在错误的文件夹中,而不是插件文件夹中。

我用以下方法解决了这个问题。

在插件启动函数中,我添加了一个伪代码来强制应用程序加载程序集,以便以后使用它

  static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            ...
            LoadLoadUiAssemblies();
            ...
        }

        public void LoadUiAssemblies()
        {
            // somehow the loading of the wpf components does not work, 
            //here we load the assembly in the cache so that we can use it
            var ts = new WPFToggleSwitch.ToggleSwitch();
        }
    }

这里是WPF中的用法

<UserControl x:Class="ViewManager.DimensionAssistantView"
             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:ViewManager"
             mc:Ignorable="d"
             xmlns:p="clr-namespace:ViewManager.Properties"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             d:DesignHeight="300" d:DesignWidth="400"

             xmlns:wts="clr-namespace:WPFToggleSwitch;assembly=WPFToggleSwitch"

             Name="balalal"
             MinWidth="100" MinHeight="100">


 <StackPanel  Grid.Row="0" 
                     HorizontalAlignment="Left" Orientation="Horizontal" 
                     IsEnabled="{Binding IsFaceSelected}" Background="WhiteSmoke">

            <wts:ToggleSwitch IsChecked="{Binding  SelectedFaceSketchsVisibleStatus}" CheckedText="un-visible" UncheckedText="Visible">
                <wts:ToggleSwitch.Content>
                    <TextBlock VerticalAlignment="Center"
                               TextWrapping="Wrap"
                               Text="{x:Static p:Resources.DAShowAllDimensionsToggleButtonText}" />
                </wts:ToggleSwitch.Content>
            </wts:ToggleSwitch>
        </StackPanel>