我正准备一个具有多个对象的应用程序,每个对象都有一个整数id和字符串数据。我希望具有相同id的对象的数据相同。我将调用此对象SharedObject(此对象的行为类似于某些数据库表的ViewModel。)
有人可能会说这很容易。您可以创建单个对象,并在每次需要时引用它。但实际上这种方式对我来说不起作用,因为我无法预测对象的创建时间和地点。
因此,为了解决这个问题,我决定在SharedObject类中放置一个静态事件,并在任何SharedObject数据发生更改时调用它(比如INotifyPropertyChanged中的PropertyChanged事件,但我的是静态的。这将使它对SharedObject的每个实例都可见) ,但问题是我最终得到了一个充满内存泄漏的程序!!
昨晚我整理出我必须使用弱事件模式来解决内存泄漏问题。
我在昨晚搜索了网络,以便完全实现弱事件模式,但我最终没有删除或删除页面。
最后,我想出了如何用弱事件模式来做到这一点 我创建了一个测试项目来测试这种方法,但它没有用, 无法调用ReceiveWeakEvent事件。
我错过了什么吗? 或者实现这种模式的正确方法是什么?
顺便说一句,我使用.net 4,因为我需要我的应用程序来支持Win XP(这是我的客户需要的,不要问我这个问题),所以我不能使用通用的WeakEventManager类。
很抱歉很长的帖子,但是这个问题让我脱掉了头发,并提前感谢。
以下是完整的应用程序代码:
SharedObject类:
public class SharedObject :INotifyPropertyChanged,IWeakEventListener
{
static WaekEvent sheardEvent = new WaekEvent();
public event PropertyChangedEventHandler PropertyChanged;
public int ID { get; private set; }
public SharedObject(int id)
{
this.ID = id;
SharedWeakEventManager.AddListener(sheardEvent, this);
}
string data;
public string Data
{
get
{
return data;
}
set
{
if(value != data)
{
data = value;
OnPropertyChanged("Data");
sheardEvent.RiseSharedEvent(this, new PropertyChangedEventArgs("Data"));
}
}
}
protected virtual void OnPropertyChanged(string propName)
{
PropertyChangedEventHandler handler;
lock (this)
{
handler = PropertyChanged;
}
if (handler != null)
handler.Invoke(this, new PropertyChangedEventArgs(propName));
}
void OnSharedPropertyChaingo(object sender,PropertyChangedEventArgs e)
{
SharedObject s = sender as SharedObject;
if (s == null || s.ID != ID)
return;
data = s.Data;
OnPropertyChanged("Data");
}
public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
{
if(managerType == typeof(SharedWeakEventManager) && sender is SharedObject)
{
OnSharedPropertyChaingo(sender, e as PropertyChangedEventArgs);
}
return false;
}
}
WaekEvent和SharedWeakEventManager类:
public class SharedObject
{
public event EventHandler SharedEvent;
public void RiseSharedEvent(object sender, EventArgs args)
{
if (SharedEvent != null)
SharedEvent.Invoke(sender, args);
}
}
public class SharedWeakEventManager : WeakEventManager
{
public static SharedWeakEventManager CurrentManager
{
get
{
var manager_type = typeof(SharedWeakEventManager);
var manager = WeakEventManager.GetCurrentManager(manager_type) as SharedWeakEventManager;
if (manager == null)
{
manager = new SharedWeakEventManager();
WeakEventManager.SetCurrentManager(manager_type, manager);
}
return manager;
}
}
public static void AddListener(WaekEvent source, IWeakEventListener listener)
{
CurrentManager.ProtectedAddListener(source, listener);
}
public static void RemoveListener(WaekEvent source, IWeakEventListener listener)
{
CurrentManager.ProtectedRemoveListener(source, listener);
}
protected override void StartListening(object source)
{
((WaekEvent)source).SharedEvent += this.DeliverEvent;
}
protected override void StopListening(object source)
{
((WaekEvent)source).SharedEvent -= this.DeliverEvent;
}
}
MainWindow的XAML部分:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListView x:Name="View" Margin="10,49,10,10" SelectionChanged="ListView_SelectionChanged">
<ListView.View>
<GridView>
<GridViewColumn Header="ID" Width="100" DisplayMemberBinding="{Binding ID}"/>
<GridViewColumn Header="Data" Width="100" DisplayMemberBinding="{Binding Data}"/>
</GridView>
</ListView.View>
</ListView>
<Button Content="New" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="10,13.01,0,0" Click="Button_Click"/>
<TextBox x:Name="IDText" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="92" Margin="136.2,11,0,0"/>
<TextBox x:Name="DataText" HorizontalAlignment="Left" Height="23" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="92" Margin="280.799,11,0,0" TextChanged="DataText_TextChanged"/>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="ID" VerticalAlignment="Top" Margin="119.593,14,0,0"/>
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Data" VerticalAlignment="Top" Margin="251.106,15.01,0,0"/>
<Button Content="Remove" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="377.799,12,0,0" Click="Button_Click_1"/>
</Grid>
MainWindow类:
public partial class MainWindow : Window
{
private ObservableCollection<SharedObject> sharedObjects;
public ObservableCollection<SharedObject> SharedObjects
{
get
{
if (sharedObjects == null)
sharedObjects = new ObservableCollection<SharedObject>();
return sharedObjects;
}
}
public SharedObject SelelectedObject { get; set; }
public MainWindow()
{
InitializeComponent();
View.ItemsSource = SharedObjects;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
int id;
if (!int.TryParse(IDText.Text, out id))
return;
SharedObject x = new SharedObject(id);
x.Data = DataText.Text;
SharedObjects.Add(x);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (SelelectedObject == null)
return;
SharedObjects.Remove(SelelectedObject);
SelelectedObject = null;
}
private void DataText_TextChanged(object sender, TextChangedEventArgs e)
{
if (SelelectedObject != null)
SelelectedObject.Data = DataText.Text;
}
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelelectedObject = View.SelectedItem as SharedObject;
if (SelelectedObject == null)
return;
IDText.Text = SelelectedObject.ID.ToString();
DataText.Text = SelelectedObject.Data;
}
}