简体   繁体   English

WPF从Web向应用程序的不同部分提供数据

[英]Wpf providing data from web to different parts of application

I have a WPF application that gets data from a web-server. 我有一个WPF应用程序,可从Web服务器获取数据。

It contains two Views 它包含两个视图

  • LeftView
  • RightView

three Models 三种模式

  • LeftModel
  • RightModel
  • CentralModel

and two ViewModels 和两个ViewModel

  • LeftViewModel
  • RightViewModel

I will show only LeftView , LeftViewModel , LeftModel , and CentralModel (too much code). 我将只显示LeftViewLeftViewModelLeftModelCentralModel (太多代码)。 You can find the entire project here . 您可以在此处找到整个项目。

I guess the main problem is that the UpdateCollection() have high coupling with public ObservableCollection<SomeTypeA> Items {get; set;} 我猜主要的问题是UpdateCollection()public ObservableCollection<SomeTypeA> Items {get; set;} public ObservableCollection<SomeTypeA> Items {get; set;} . public ObservableCollection<SomeTypeA> Items {get; set;}

Therefore I have the feeling that I cannot place UpdateCollection() in CentralModel . 因此,我CentralModel无法将UpdateCollection()放在CentralModel中的CentralModel

I think it will be better if UpdateCollection() will be in CentralModel how to make that? 我认为,如果UpdateCollection()将在CentralModel进行制作会更好一些?

Work logic is very simple, incoming message from web server add into public Dictionary<string, Action<MessageReceivedEventArgs>> Handle { get; set; } 工作逻辑非常简单,来自Web服务器的传入消息被添加到public Dictionary<string, Action<MessageReceivedEventArgs>> Handle { get; set; } public Dictionary<string, Action<MessageReceivedEventArgs>> Handle { get; set; }

        public void Message(object sender, MessageReceivedEventArgs e)
    {
        var dresult = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, SomeTypeA>>(e.Message);
        if (Handle.ContainsKey(dresult.Keys.ToList()[0]))
        {
            Handle[dresult.Keys.ToList()[0]](e);
        }
    }

, if dictionary contains key, it firing event in model ,如果字典包含键,则会在模型中触发事件

CentralModel.Instance.Handle.Add("central_office", (m) =>
        {
            var dresult = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, SomeTypeA>>(m.Message);
            Console.WriteLine(m.Message.ToString());
            foreach (KeyValuePair<string,SomeTypeA> item in dresult)
            {
                if (!Items.Any(key=>key.ID==dresult["central_office"].ID))
                {
                    Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => Items.Add(item.Value)));
                }
                foreach (SomeTypeA subitem in Items)
                {
                    subitem.ID = item.Value.ID;
                    subitem.Name = item.Value.Name;
                    subitem.Value = item.Value.Value;
                    subitem.Work = item.Value.Work;
                    subitem.Department = item.Value.Department;
                }
            }
        });

ServerClass.cs ServerClass.cs

namespace Server
{
class ServerClass
{
    private WebSocketServer appServer;

    public void Setup()
    {
        appServer = new WebSocketServer();

        if (!appServer.Setup(2012)) //Setup with listening port
        {
            Console.WriteLine("Failed to setup!");
            Console.ReadKey();
            return;
        }

        appServer.NewMessageReceived += new SessionHandler<WebSocketSession, string>(appServer_NewMessageReceived);

        Console.WriteLine();
    }

    public void Start()
    {
        if (!appServer.Start())
        {
            Console.WriteLine("Failed to start!");
            Console.ReadKey();
            return;
        }

        Console.WriteLine("The server started successfully! Press any key to see application options.");

        SomeTypeA FirstWorker = new SomeTypeA()
        {
            Department = "Finance",
            ID = "0",
            Name = "John",
            Work = "calculate money"
        };
        SomeTypeB SecondWorker = new SomeTypeB()
        {
            ID = "1",
            Name = "Nick",
            Work = "clean toilet"
        };

        while (true)
        {
            FirstWorker.value += 1;
            SecondWorker.value += 5;
            Dictionary<string, SomeTypeA> Element1 = new Dictionary<string, SomeTypeA>();
            Element1.Add("central_office", FirstWorker);
            Dictionary<string, SomeTypeB> Element2 = new Dictionary<string, SomeTypeB>();
            Element2.Add("back_office", SecondWorker);
            string message1 = Newtonsoft.Json.JsonConvert.SerializeObject(Element1);
            string message2 = Newtonsoft.Json.JsonConvert.SerializeObject(Element2);

            System.Threading.Thread.Sleep(2000);
            foreach (WebSocketSession session in appServer.GetAllSessions())
            {
                session.Send(message1);
                session.Send(message2);
            }
        }
    }

    private void appServer_NewMessageReceived(WebSocketSession session, string message)
    {
        Console.WriteLine("Client said: " + message);
        session.Send("Server responded back: " + message);
    }
}
}

Program.cs Program.cs

namespace Server
{
class Program
{
    static void Main(string[] args)
    {
        ServerClass myServer = new ServerClass();
        myServer.Setup();
        myServer.Start();
    }
}
}

LeftView.cs LeftView.cs

<Grid>
    <ListView ItemsSource="{Binding LM.Items}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                        <ColumnDefinition></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Label Grid.Column="0" Content="{Binding Name}"></Label>
                    <Label Grid.Column="1" Content="{Binding Work}"></Label>
                    <Label Grid.Column="2" Content="{Binding Value}"></Label>
                    <Label Grid.Column="3" Content="{Binding ID}"></Label>
                    <Label Grid.Column="4" Content="{Binding Department}"></Label>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

LeftViewModel.cs LeftViewModel.cs

namespace WpfApplication139.ViewModels
{
public class LeftViewModel
{
    public LeftModel LM { get; set; }
    public LeftViewModel()
    {
        LM = new LeftModel();
    }
}
}

LeftModel.cs LeftModel.cs

namespace WpfApplication139.Models
{
public class LeftModel
{
    public ObservableCollection<SomeTypeA> Items {get; set;}
    public LeftModel()
    {
        Items = new ObservableCollection<SomeTypeA>();
        CentralModel.Instance.Setup("ws://127.0.0.1:2012", "basic", WebSocketVersion.Rfc6455);
        CentralModel.Instance.Start();
        UpdateCollection();
    }

    public void UpdateCollection()
    {
        CentralModel.Instance.Handle.Add("central_office", (m) =>
        {
            var dresult = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, SomeTypeA>>(m.Message);
            Console.WriteLine(m.Message.ToString());
            foreach (KeyValuePair<string,SomeTypeA> item in dresult)
            {
                if (!Items.Any(key=>key.ID==dresult["central_office"].ID))
                {
                    Application.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() => Items.Add(item.Value)));
                }
                foreach (SomeTypeA subitem in Items)
                {
                    subitem.ID = item.Value.ID;
                    subitem.Name = item.Value.Name;
                    subitem.Value = item.Value.Value;
                    subitem.Work = item.Value.Work;
                    subitem.Department = item.Value.Department;
                }
            }
        });
    }
}
}

CentralModel.cs 中央模型

namespace WpfApplication139.Models
{
public class CentralModel
{
    private WebSocket websocketClient;

    private string url;
    private string protocol;
    private WebSocketVersion version;

    private static CentralModel instance;

    public Dictionary<string, Action<MessageReceivedEventArgs>> Handle { get; set; }
    private CentralModel()
    {
        Handle = new Dictionary<string, Action<MessageReceivedEventArgs>>();
    }
    public void Setup(string url, string protocol, WebSocketVersion version)
    {
        this.url = url;
        this.protocol = protocol;
        this.version = WebSocketVersion.Rfc6455;

        websocketClient = new WebSocket(this.url, this.protocol, this.version);
        websocketClient.MessageReceived += new EventHandler<MessageReceivedEventArgs>(CentralModel.Instance.Message);
    }
    public void Start()
    {
        websocketClient.Open();
    }
    public static CentralModel Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new CentralModel();
            }
            return instance;
        }
    }
    public void Message(object sender, MessageReceivedEventArgs e)
    {
        var dresult = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, SomeTypeA>>(e.Message);
        if (Handle.ContainsKey(dresult.Keys.ToList()[0]))
        {
            Handle[dresult.Keys.ToList()[0]](e);
        }
    }
}
}

SomeTypeA and SomeTypeB using for json serealization of two types of messages. SomeTypeA和SomeTypeB用于将json两种消息类型化。

SomeTypeA.cs SomeTypeA.cs

public class SomeTypeA
{
    public string Name { get; set; }
    public string Work { get; set; }
    public string ID { get; set; }
    public int value { get; set; }
    public string Department { get; set; }
}

SomeTypeB.cs SomeTypeB.cs

public class SomeTypeB
{
    public string Name { get; set; }
    public string Work { get; set; }
    public string ID { get; set; }
    public int value { get; set; }
}

I'm doing this on my phone, so code examples might look rubbish, sorry. 我在手机上执行此操作,因此代码示例可能看起来很垃圾,抱歉。

First off, if you're going to use your own classes to define your JSON models, Newtonsoft isn't really needed. 首先,如果您要使用自己的类来定义JSON模型,则实际上并不需要Newtonsoft。 That's an extra assembly you have to license correctly. 那是您必须正确许可的额外程序集。 Use the built in JavaScriptSerializer from the assembly 使用程序集中的内置JavaScriptSerializer

System.Web.Extensions

If you're going to deserialize the data into a dictionary, just use the built in classes. 如果要将数据反序列化为字典,则只需使用内置的类。

Refer to this url for creating classes that can be used to deserialize your JSON data: json2csharp 请参考以下URL以创建可用于反序列化JSON数据的类: json2csharp

So, with JSON like this 因此,使用这样的JSON

{
    "name": "My Name",
    "age": "22",
    "info": {
        "social": [
            "Facebook", "Twitter", "Google+"
        ]
    }
}

C# would be like C#就像

public class Info
{
     public List<string> social { get; set; }
}

public class RootObject
{
    public string name { get; set; }
    public string age { get; set; }
    public Info info { get; set; }
}

...
RootObject JSON= new JavaScriptSerializer().Deserialize<RootObject>(myJSONData);
...

You can then bind the RootObject to your list view and use the different properties in your data binding to get the information. 然后,您可以将RootObject绑定到列表视图,并在数据绑定中使用其他属性来获取信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM