为共享属性MVVM

时间:2016-01-23 17:10:47

标签: c# .net wpf mvvm weak-events

我正准备一个具有多个对象的应用程序,每个对象都有一个整数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;
    }
}

0 个答案:

没有答案