私は賢明です。初心者からWPFへ、どこが間違っているのか分からない。WPFアプリケーションとInterop - シングルトンが複数回インスタンス化されています
私は、さまざまなメタデータと共に、選択されたテキストをキャプチャする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これは
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>
問題がある私のViewModelにある道具は一方で、
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
}
をINotifyPropertyChangedのことを私が作ったカスタムクラスでありますエンryがmymodelの作成リストに追加されても問題ありません.OnPropertyChanged()のハンドラは常にnullと等しくなります。これは、私がViewModelがインスタンス化されていることを知っているにもかかわらず(メッセージボックスがポップアップするため)
FWIW、モデル、ViewModel、WPF、およびAddInはすべて異なるアセンブリにあります。 Viewmodelは、そのコンストラクタ内でモデルのイベントを購読しています。だから、私のハンドラはnullと呼ばれます。
UPDATE
同僚とこれを議論した後、私は問題はMS WordのADDINとVMの両方がモデルを構成する方法にあり実現しました。どちらも別のスレッドで実行されており、明らかに両方とも私のSingletonの別のインスタンスを保持しています!私はそれがどう起こっているのか分かりません。プライベートインスタンスを "揮発性"にし、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は、別々のインスタンスを保持しています。私は何が欠けていますか?
お返事ありがとうございます!しかし、それは問題ではありません。 ViewModelはモデルからイベントをキャプチャします。これにより、VMは自身のイベントを起動し、xamlはそのバインディングからキャプチャするため、問題はありません。 – Moe45673