[编辑] 重复此问题的示例Host to AddIn issue
我正在尝试编写可扩展且使用少量接口的主机应用程序。其中之一是
public MessageCreator GetMessageCreator()
{
var creator = new AVL2MessageCratorFactory();
return creator.Create(new AVL2DataForMessageCreatingImpl { Imei = VM.Imei });
}
从AddIn及以下,您可以找到AddIn客户应用程序的XAML:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:AVL2SimulatorAddView="clr-namespace:AVL2SimulatorAddView" x:Class="AVL2SimulatorAddView.AVL2AddInUI">
<Grid Height="46" Width="344">
<Grid.DataContext>
<AVL2SimulatorAddView:AVL2ViewModel x:Name="VM" />
</Grid.DataContext>
<Label Content="Starting IMEI" Margin="0,0,255,0" Height="29" VerticalAlignment="Top" />
<TextBox Text="{Binding Path=Imei, UpdateSourceTrigger=PropertyChanged }" Margin="120,2,48,0" Width="176" Height="27" VerticalAlignment="Top" />
</Grid>
来自ViewModel的Imei属性
using System.ComponentModel;
namespace AVL2SimulatorAddView
{
public class AVL2ViewModel : INotifyPropertyChanged
{
readonly AVL2Model _avl2Model = new AVL2Model();
public string Imei
{
get { return _avl2Model.Imei; }
set
{
if (value == _avl2Model.Imei) return;
_avl2Model.Imei = value;
OnPropertyChanged("Imei");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
在调试模式下我看到ViewModel中的属性被更新,每个字符都写在TextBox中,但是当调用来自Host应用程序的GetMessageCreator()时,它似乎是新的空虚拟机及其Imei被返回(我没看到Imei on主持申请方)
我是否因为绕过绑定数据而错过了.Net中的一些保护措施?其他&#34;硬编码&#34;字符串传递得很好。主机应用程序端的MVVM和DataContext也很有效。我尝试了不同类型的UpdateSourceTrigger,但它似乎总是在AddIn端工作,并且它不向共享接口提供当前日期。
[编辑] 绑定到Imei的其他控件,在文本框中输入数据时在线显示更改
调用本地按钮正确设置标签内容
private void button1_Click(object sender, RoutedEventArgs e)
{
label1.Content = VM.Imei;
}
来自主机应用程序的临时调用方法
var msgCreator = _tabsMap[(TabItem) tabControl1.SelectedItem].GetMessageCreator();
答案 0 :(得分:1)
我指的是你的演示项目。在LoadGeneratorWPFHostApplication.MainWindow
的构造函数中考虑此代码:
// Activate creates instance AAddIn#1 (wpfAddInHostView.wpfAddInContract.wpfAddInView)
foreach (var wpfAddInHostView in addInTokens.Select(addInToken => addInToken.Activate<IWpfAddInHostView>(AddInSecurityLevel.Host)))
{
// AAddin#1.GetAddinUI creates instance AAddIn#2 (tabItem.Content)
var tabItem = new TabItem {Content = wpfAddInHostView.GetAddInUI(), Header = wpfAddInHostView.GetName()};
tabControl1.Items.Add(tabItem);
// adding AAddIn#1 to _tabsMap (but using AAddIn#2 on the UI).
_tabsMap.Add(tabItem, wpfAddInHostView);
}
所以这里发生的是你使用System.AddIn.Hosting.AddInToken.Activate
来创建AAddIn
(#1)的实例。但在此之后,您使用此AAddIn#1以其方法GetAddInUI
创建另一个实例。
public partial class AAddIn : WPFAddInView
{
public FrameworkElement GetAddInUI()
{
return new AAddIn(); // creates a new instance of itself
}
}
AAddIn#1在合同(WPFAddIn_ContractToViewHostSideAdapter.wpfAddInContract.wpfAddInView
)上保留,在_tabsMap
中,AAddIn#2在UI中使用(tabItem.Content
)。
有多种方法可以确保您保持相同的实例,我可能只是从GetAddInUI
界面(注:always start interface names with an I)以及{{{{}}}中删除WPFAddInView
方法1}} class,然后直接在合同上返回AAddIn
:
wpfAddInView
旁注:在调试器中使用方法public class WPFAddIn_ViewToContractAddInSideAdapter : ContractBase, IWPFAddInContract
{
public INativeHandleContract GetAddInUI()
{
FrameworkElement fe = this.wpfAddInView as FrameworkElement; // return instance directly instead of creating new one by wpfAddInView.GetAddInUI();
INativeHandleContract inhc = FrameworkElementAdapters.ViewToContractAdapter(fe);
return inhc;
}
}
来区分同一个类的实例。