C# 从单独的类库访问UI控件
我的解决方案包含一个名为Manager的库(其中一个类名为ProductionManager)以及一个WPF项目。 我想要ProductionManager类的一种方法来访问WPF的C# 从单独的类库访问UI控件,c#,wpf,xaml,dispatcher,C#,Wpf,Xaml,Dispatcher,我的解决方案包含一个名为Manager的库(其中一个类名为ProductionManager)以及一个WPF项目。 我想要ProductionManager类的一种方法来访问WPF的UIcontrol,我该怎么做 更具体地说,我的UI有一个按钮和一个文本框。按下按钮,我从我的库中调用一个方法,我想从中更新UI窗口中的TextBox 我知道我应该使用调度程序来执行此操作,但我不知道如何正确设置它。有人能帮忙吗 此处显示MainWindow.xaml: 这里是我的经理库中的ProductionMan
UIcontrol
,我该怎么做
更具体地说,我的UI
有一个按钮和一个文本框
。按下按钮,我从我的库中调用一个方法,我想从中更新UI
窗口中的TextBox
我知道我应该使用调度程序
来执行此操作,但我不知道如何正确设置它。有人能帮忙吗
此处显示MainWindow.xaml:
这里是我的经理库中的ProductionManager类
有人能帮我吗?你可以试试这样的东西 在
Dosomethingelse()方法中,获取对文本框的引用
public void Dosomethingelse(TextBox textBox,string yourText)
{
var myTextbox = textbox;
mytextbox.text = yourText;
}
现在,当您从MainWindows.xaml.cs
调用此方法时
myManager.Dosomethingelse(tbox_data,stringYouWantToAdd);
好的,解决了!,我从s的一个答案中找到了这个方法
首先,必须为主窗口创建一个静态变量。所以你的图书馆可以访问它。您必须创建一个字符串属性来设置文本框的文本。然后在该属性的设置访问器中,您可以使用dispatcher更改文本
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public ProductionManager myManager;
public MainWindow()
{
InitializeComponent();
myManager = new ProductionManager();
window = this;
}
internal static MainWindow window;
public string myString
{
get { return myTextBox.Text; }
//this is where you change the text of your text box
set { Dispatcher.Invoke(new Action(() => { myTextBox.Text = value; })); }
}
private void Button_Click(object sender, RoutedEventArgs e)
{
myManager.DoSomething("Hello world");
}
}
现在编辑“DoSomething()”方法,如下所示:
public void Dosomethingelse(string text)
{
MainWindows.window.myString = text;
}
可以使用事件系统和SynchronizationContext类,这样就不需要额外的库
namespace Manager
{
public class ProductionManager
{
private static ProductionManager instance;
// Store the UI context
private readonly SynchronizationContext _UIContext;
// Define event handler signature
public delegate void TextChangedHandler(object sender, TextEventArgs e);
// Define the event to listen for in your MainWindow
public event TextChangedHandler TextChangeEvent;
private ProductionManager()
{
// Set the SynchronizationContext, make sure to call your Instance from the MainWindow
_UIContext = SynchronizationContext.Current;
}
public static ProductionManager Instance
{
get
{
if (instance == null)
{
instance = new ProductionManager();
}
return instance;
}
}
public void DoSomethingElse()
{
// Don't change the TextBox here send the event to the MainWindow instead
// Use the SynchronizationContext to invoke the event
_UIContext.Send(o => TextChangeEvent?.Invoke(this, new TextEventArgs("Hello World!"), null);
}
}
// The TextEventArgs, change for your needs.
public class TextEventArgs : EventArgs
{
public TextEventArgs(string text) : base()
{
Text = text;
}
public string Text { get; }
}
}
更改主窗口
public partial class MainWindow : Window
{
private ProductionManager myManager = ProductionManager.Instance;
public MainWindow()
{
InitializeComponent();
// Hookup the event listener
myManager.TextChangeEvent += UpdateTextBox;
}
private void UpdateTextBox(object sender, TextEventArgs e)
{
// Finally handle your text change here
tbox_Data.Text = e.Text;
}
private void btnRun_Click(object sender, RoutedEventArgs e)
{
myManager.DoSomethingElse();
}
}
您希望在Dosomethingelse
方法中处理的逻辑,在其他库中放置与UI控件相关的逻辑不是一个好的做法。在Dosomethingelse中,我希望将textbox.Text属性更改为“Hello World”。总之,我正试图通过这个简单的应用程序了解更多关于dispatcher的信息。TanksYou可以这样做,public void Dosomethingelse(Button dobject){Dispatcher.Invoke((Action)(()=>dobject.Content=“Hello World”);}
我想这样做,但如果我这样做,我将不得不将我的库与WPF应用程序紧密结合。如果我可以从库中调用UI的调度程序,我就可以访问任何UI控件,而无需对单个方法进行任何引用。我甚至想在ProductionManager.cs中添加一个公共窗口myWin。我可以在initialize()之后立即在MainWindow.xaml.cs中初始化myWin;呼叫你觉得呢?我觉得你应该多了解一下调度员。我们使用dispatcher来确定任务的优先级。本文将对您有所帮助,谢谢您,但是虽然解决方案中的WPF项目引用了库,但我的库没有引用WPF以避免循环引用。这意味着库无法识别MainWindows类。你能解决这个问题吗?你可以通过使用Action来解决这个问题,但我不知道如何使用dispatcher来解决这个问题。因为您无法通过UIs的dispatcher从库类访问ui线程。因为该调度程序属于UI线程。
public void Dosomethingelse(string text)
{
MainWindows.window.myString = text;
}
namespace Manager
{
public class ProductionManager
{
private static ProductionManager instance;
// Store the UI context
private readonly SynchronizationContext _UIContext;
// Define event handler signature
public delegate void TextChangedHandler(object sender, TextEventArgs e);
// Define the event to listen for in your MainWindow
public event TextChangedHandler TextChangeEvent;
private ProductionManager()
{
// Set the SynchronizationContext, make sure to call your Instance from the MainWindow
_UIContext = SynchronizationContext.Current;
}
public static ProductionManager Instance
{
get
{
if (instance == null)
{
instance = new ProductionManager();
}
return instance;
}
}
public void DoSomethingElse()
{
// Don't change the TextBox here send the event to the MainWindow instead
// Use the SynchronizationContext to invoke the event
_UIContext.Send(o => TextChangeEvent?.Invoke(this, new TextEventArgs("Hello World!"), null);
}
}
// The TextEventArgs, change for your needs.
public class TextEventArgs : EventArgs
{
public TextEventArgs(string text) : base()
{
Text = text;
}
public string Text { get; }
}
}
public partial class MainWindow : Window
{
private ProductionManager myManager = ProductionManager.Instance;
public MainWindow()
{
InitializeComponent();
// Hookup the event listener
myManager.TextChangeEvent += UpdateTextBox;
}
private void UpdateTextBox(object sender, TextEventArgs e)
{
// Finally handle your text change here
tbox_Data.Text = e.Text;
}
private void btnRun_Click(object sender, RoutedEventArgs e)
{
myManager.DoSomethingElse();
}
}