使用Interop的WPF应用程序 - Singleton不止一次实例化

时间:2016-05-02 21:42:08

标签: c# .net wpf events inotifypropertychanged

我在我的智慧结束。 WPF的新手如此不确定我哪里出错了。

我有一个MS Word Interop插件,可以捕获选定的文本以及各种元数据。它组成我的模型并将数据传递给它。

对于这个开发阶段,我让我的模型成为单身,这样我就知道一切都指向同一个参考。

无论如何,我的模型由一系列条目组成。

public sealed class MYMODELSingleton : ObservableObject, IMYMODEL
{




    private static MYMODELSingleton instance;

    private MYMODELSingleton()
    {
        isActive = true;

        EntryList = new List<MyEntry.IMyEntry>();
    }

    public static MYMODELSingleton Instance
    {
        get
        {
            if(instance == null)
            {
                instance = new MYMODELSingleton();
            }
            return instance;
        }
    }
    public bool isActive { get; set; }

    private List<MyEntry.IMyEntry> _entryList;

    public List<MyEntry.IMyEntry> EntryList
    {
        get { return _entryList; }
        set { _entryList = value; OnPropertyChanged("EntryList"); }
    }

    public void Add(IMYEntry mEntry)
    {
        try {
            EntryList.Add(mEntry);

            OnPropertyChanged("EntryList");
        }
        catch(ArgumentException ae)
        {
            throw ae;
        }
    }

ObservableObject是我制作的实现INotifyPropertyChanged

的自定义类
public abstract class ObservableObject : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members

    /// <summary>
    /// Raised when a property on this object has a new value.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Raises this object's PropertyChanged event.
    /// </summary>
    /// <param name="propertyName">The property that has a new value.</param>
    protected virtual void OnPropertyChanged(string propertyName)
    {

   #if DEBUG
        MessageBox.Show("Inside Event!");
   #endif

        var handler = this.PropertyChanged;
        if (handler != null)
        {
  #if DEBUG
            MessageBox.Show("Event Fired!");
  #endif
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }

    #endregion // INotifyPropertyChanged Members

}

这是我的ViewModel

public class MyEntryViewModel : ObservableObject
{

    private MYMODELSingleton activeMYMODEL= MYMODELSingleton.Instance; 


    public MyProjectModel.MYMODEL.MYMODELSingleton ActiveMYMODEL
    {
        get
        {
            return activeMYMODEL;
        }
        set
        {
            activeMYMODEL = value;
            OnPropertyChanged("ActiveMYMODEL");
        }
    }

    private void ModelPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "EntryList") {
            int index = activeMYMODEL.EntryList.Count - 1;
            MyEntry = activeMYMODEL.EntryList[index];
            UpdateGui(MyEntry.Source);
        }
    }

    public void UpdateGui(SelectionState selState)
    {
        TxtDocName = selState.SelectionDocName;
        TxtDocPage = selState.SelectionPage;
        TxtDocText = selState.SelectionText;
    }  



    public MyEntryViewModel()
    {
        this.MyEntry = new MyEntry();


        activeMYMODEL.PropertyChanged += new PropertyChangedEventHandler(ModelPropertyChanged);

        //This is to notify me when the VM is created
#if DEBUG
        System.Windows.Forms.MessageBox.Show("ViewModelOpened!");
#endif





    }

    ~MyEntryViewModel()
    {
        activeMYMODEL.PropertyChanged -= new PropertyChangedEventHandler(this.ModelPropertyChanged);
#if DEBUG
        System.Windows.Forms.MessageBox.Show("ViewModel Closed!");
#endif
    } 





}
}

相关WPF代码

xmlns:custns="clr-namespace:MyProjectViewModel.MyEntryViewModel;assembly=MyProjectViewModel"

    Title="MyProject" Height="350" Width="525" SizeToContent="Height">
<Window.Resources>
    <custns:MyyEntryViewModel x:Key="MyProjectObj" />
</Window.Resources>
<Grid Name="gridEntry" DataContext="{StaticResource MyProjectObj}" >
<TextBlock x:Name="docNameTxtBx" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="20" TextWrapping="Wrap" Text="{Binding TxtDocName, UpdateSourceTrigger=PropertyChanged}"  />
</Grid>

问题是,当条目被添加到mymodel的组合List没问题时,OnPropertyChanged()中的处理程序总是等于null。尽管事实上我知道ViewModel已经实例化(由于消息框弹出)。

FWIW,Model,ViewModel,WPF和AddIn都在不同的程序集中。 Viewmodel在其构造函数中订阅了Model的事件,那么为什么我的处理程序在调用时为null?

<小时/> 更新

在与同事讨论之后,我意识到问题在于MS Word ADDIN和VM如何组成模型。两者都在不同的线程中运行,显然,两者都持有我的Singleton的单独实例!我不确定这是怎么回事。我甚至改变了我的Singleton代码,使私有实例“易变”并添加一个静态Object,然后在调用Instance.get()时锁定。

    private static volatile MyModelSingleton instance;
    private static object syncRoot = new Object();

    private MyModelSingleton()
    {
        isActive = true;

        EntryList = new List<MyEntry.IMyFEntry>();
    }

    public static MyModelSingleton Instance
    {
        get
        {
            lock (syncRoot)
            {
                if (instance == null)
                {

                    instance = new MyModelSingleton();
                }
            }
            return instance;
        }
    }

尽管如此,Word Interop Addin和Viewmodel都包含单独的实例。我错过了什么?

1 个答案:

答案 0 :(得分:0)

在您提供的wpf代码中,您永远不会绑定ActiveMYMODEL。因为它永远不会绑定在你的xaml中,所以你永远不会挂钩通知你创建的属性更改事件。