我的ViewModel不提供当前变量值

时间:2014-10-20 12:23:17

标签: c# wpf mvvm add-in

[编辑] 重复此问题的示例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();

1 个答案:

答案 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; } } 来区分同一个类的实例。

enter image description here