使用inotifypropertychanged C#WPF更新包含多个字符串的文本框 [英] Updating textbox with multiple strings using inotifypropertychanged C# WPF

查看:42
本文介绍了使用inotifypropertychanged C#WPF更新包含多个字符串的文本框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

美好的一天,



我对C#相对较新,并且刚刚实现了INotifypropertychanged。



我正在研究从CANbus读取ECU数据的项目,当我收到数据时,我正在使用INotifypropertychanged来更新带有接收数据的UI 。



这种方法运行良好而且快速但是每次收到数据时,都会覆盖previos数据(显然) - 有没有办法将数据存储在列表或调用中propertychanged每次都在文本框的新/下一行打印?



谢谢



< b>我尝试了什么:



尝试创建一个可观察的集合,但无法更新列表。

解决方案

下面的示例应该适用于ListView - 您可以使用列表框轻松替换listview。如果您对此有任何疑问,请告诉我。



 使用系统; 
使用 System.Windows;
使用 System.Windows.Controls;
使用 System.Collections.ObjectModel;

命名空间 ListViewTest.Test2
{
public partial class ListViewTest:Window
{
/// < 摘要 >
/// ObservableCollection用于存储listview中显示的数据
/// < / summary >
ObservableCollection< ; GAMEDATA> _GameCollection = new ObservableCollection< GameData>();

/// < 摘要 >
/// 标准构造函数填写ListView
/// via Observable collection with three items
/// < span class =code-summarycomment>< / summary >
public ListViewTest()
{
_GameCollection.Add( new GameData
{
GameName = 魔兽世界
Creator = 暴雪
发布者= 暴雪
});

_GameCollection.Add( new GameData
{
GameName = Halo
Creator = Bungie
发布者= Microsoft
});

_GameCollection.Add( new GameData
{
GameName = Gears Of War
Creator = Epic
Publisher = Microsoft
});

InitializeComponent();
}

public ObservableCollection< GameData> GameCollection
{
get { return _GameCollection; }
}

/// < 摘要 >
/// 点击按钮事件向ObservableCollection添加新元素
/// - >该事件被转发到listview
/// 稍后会显示更改...
/// < / summary >
/// < param < span class =code-summarycomment> name =sender > < / param >
/// < param name =e > < / param > ;
private void AddRow_Click( object sender,RoutedEventArgs e)
{
_GameCollection.Add( new GameData
{
GameName = 新游戏
Creator = 新造物主
发布者= 新发布商
});
}
}

/// < 摘要 >
/// 要存储在ObservableCollection中并在Listview中显示的简单类
/// < / summary >
public class GameData
{
public string GameName { get ; set ; }
public string 创建者{ get ; set ; }
public string 发​​布商{ get ; set ; }
}
}





 <  窗口    x:Class   =  ListViewTest.Test2.ListViewTest  

xmlns = < span class =code-keyword> http://schemas.microsoft.com/winfx/2006/xaml/presentation
< span class =code-attribute>
xmlns:x = HTTP: //schemas.microsoft.com/winfx/2006/xaml\"

DataContext = {Binding RelativeSource = {RelativeSource Self}}

标题 = 某些游戏数据 高度 = 216 宽度 = 435 >

< 网格 >
< ; Grid.RowDefinitions >
< RowDefinition 高度 = 自动 / >
< < span class =code-leadattribute> RowDefinition 高度 = 自动 / >
< / Grid.RowDefinitions >

< span class =code-keyword>< TextBlock Grid.Row = 0 TextWrapping = WrapWithOverflow 保证金 = < span class =code-keyword> 3 >
这说明如何在XAML中使用静态信息来实现ListView(请参阅ListView项目)
以及如何填充信息在ListView中通过绑定数据源使用
< TextBlock FontWeight = 粗体 > ObservableCollection < / TextBlock >
(请参阅ListViewTest项目)。
< / TextBlock >

< StackPanel Grid.Row = 1 >
< ListView ItemsSource = {Binding GameCollection} >
< ; ListView.View >
< GridView >
< GridViewColumn < span class =code-attribute> 宽度 = 140 标题 = 游戏名称 DisplayMemberBinding = {Binding GameName} / >
< span class =code-keyword>< GridViewColumn 宽度 = 140 标题 = 创建者 DisplayMemberBinding = {Binding Creator} / >
< GridViewColumn 宽度 = 140 标题 = 发布商 DisplayMemberBinding = {绑定发布者} / >
< / GridView > ;
< / ListView.View >
< / ListView >
< 按钮 Horizo​​ntalAlignment = < span class =code-attribute>保证金
= 5,5,5,5

内容 = 添加行 点击 < span class =code-keyword> = AddRow_Click / >
< / StackPanel >
< / Grid >
< / Window >


< blockquote> @Dirk,



请看下面,我试图做一个简单的应用程序突出显示问题,

- Mainwindow创建一个实例MainViewModel创建TcpConnection类的实例。

- 可观察集合在TcpConnection类中创建

- 在测试期间将数据添加到可观察集合_CanMessage

- 但它永远不会更新到绑定Listview



我不完全确定xaml中的绑定名称所以可能会有问题..



如果您有任何其他问题,请与我们联系。





 使用系统; 
使用 System.Collections.Generic;
使用 System.Collections.ObjectModel;
使用 System.ComponentModel;
使用 System.Net.Sockets;
使用 System.Threading;
使用 System.Windows;
使用 静态 SampleProj.MainViewModel;

命名空间 SampleProj
{
public partial class MainWindow:Window
{
MainViewModel _main;
public MainWindow()
{
InitializeComponent();
_main = new MainViewModel();
DataContext = _main;
}

private void Connect_Button_Click( object sender,RoutedEventArgs e)
{
_main.Client.Connect();
}

private void Start_Button_Click( object sender,RoutedEventArgs e)
{
byte [] data = { 42 0 17 2 0 22 0 0 22 43 };
_main.Client.Write(data);
}
}

MainViewModel:ObservableObject
{
public TcpConnection Client { get ; private set ; }

public MainViewModel()
{
Client = new TcpConnection();
}

public class 消息
{
public string CANMessage { get ; set ; }
}
}

public class TcpConnection :ObservableObject
{
TcpClient客户端;
Thread threadClientReceive;
NetworkStream clientStream;

ObservableCollection< Message> _CanMessage = new ObservableCollection< Message>();

bool receiveThreadAlive = false ;
bool flagThreadRunning = false ;
bool clientIsConnected = false ;

string identifier = string .Empty;
string data = string .Empty;

public TcpConnection()
{

}

public void Connect()
{
client = new TcpClient();
var result = client.BeginConnect( 192.168.0.1 10000 null );
var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds( 2 ));
threadClientReceive = new 线程( new ParameterizedThreadStart(TcpReceive));
flagThreadRunning = true ;
receiveThreadAlive = true ;
threadClientReceive.Start(client);

if (!success)
{
throw new 异常();
}

if (client.Connected)
{
clientIsConnected = ;
}
}


public void TcpReceive( object client)
{
string bitString = .Empty;
bool startBitFound = false ;
byte startBit = 42 ;
byte stopBit = 43 ;
列表< byte> receiveDataList = new List< byte>();

TcpClient tcpClient =(TcpClient)客户端;
if (tcpClient.Connected)
{
clientStream = tcpClient.GetStream();
}

byte [] buffer = new byte [ 1024 ];
while (flagThreadRunning)
{
int bytesRead = 0 ;
try
{
bytesRead = clientStream.Read(buffer, 0 ,buffer.Length);
}
catch {}

if ( bytesRead == 0
{
break ;
}

for int i = 0 ; i < buffer.Length; i ++)
{
if (buffer [i] == startBit)
{
startBitFound = true ;
}

if (startBitFound)
{
receiveDataList.Add(buffer [i]);
}

if (buffer [i] == stopBit)
{
if (receiveDataList.Count == 0
break ;
else
{
string message = HexEncoding.ToString(receiveDataList .ToArray());
if (message.Length > 0
{
_CanMessage.Add( new Message {CANMessage = message});
}
startBitFound = false ;
receiveDataList.Clear();
break ;
}

}
}
}
}


public void 写( byte [] data)
{
clientStream = client.GetStream();
尝试
{
clientStream.Write(data, 0 , data.Length);
}
catch
{
}
}
}

public class HexEncoding
{
public HexEncoding()
{

}

public static string ToString( byte [] bytes)
{
string hexString = ;

for int i = 0 ; i < bytes.Length; i ++)
{
hexString + = bytes [i] .ToString(< span class =code-string>
X2);
}
return hexString;
}
}


public class ObservableObject:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

受保护 void OnPropertyChanged( string propertyName)
{
PropertyChanged?.Invoke( this new PropertyChangedEventArgs(propertyName));
}
}
}











< Window x:Class =   SampleProj.MainWindow 
xmlns = http://schemas.microsoft.com / winfx / 2006 / xaml / presentation
xmlns:x = http:// schemas.microsoft.com/winfx/2006/xaml
xmlns:d = http ://schemas.microsoft.com/expression/blend/2008
xmlns:mc = http://schemas.openxmlformats.org/markup-compatibility/2006
xmlns:local = clr-namespace:SampleProj

DataContext = {Binding RelativeSource = {RelativeSource Self}}
mc:Ignorable = d
Title = MainWindow高度= 600宽度= 525 >
< Grid Margin = 0,0,-6.6,-242.2 >
< Button Name=\"conect\" Content= \"Connect\" HorizontalAlignment=\"Left\" Margin=\"119,37 ,0,0\" VerticalAlignment=\"Top\" Width=\"75\" Click=\"Connect_Button_Click\"/>
<Button Name = \"start\" Content=\"Start Session\" HorizontalAlignment=\"Left\" Margin=\"240,37,0,0\" VerticalAlignment=\"Top\" Width=\"100\" Click=\"Start_Button_Click\"/>

<ListView ItemsSource = \"{Binding Message}\" Grid.ColumnSpan=\"5\" Grid.Column=\"2\" HorizontalAlignment=\"Left\" Height=\"489\" Margin=\"29.4,65.6,0,0\" Grid.Row=\"2\" Grid.RowSpan=\"11\" VerticalAlignment=\"Top\" Width=\"429\">
<ListView.View>
<GridView>
<GridViewColumn Width = \" 200\" Header=\"Message\" DisplayMemberBinding=\"{Binding CANMessage}\" ></GridViewColumn>

</GridView>
</ListView.View>
</ListView>

</Grid>
</Window>


Good day,

I am relatively new to C# and have just got the hang of implementing INotifypropertychanged.

I am working on a project reading data off an ECU from the CANbus, and as I receive the data I am currently using INotifypropertychanged to update the UI with the received data.

This works well and fast however each time data is received, the previos data is overwritten(obviously) - is there any way to store the data in a list or call propertychanged to print in a new/next line of the textbox each time??

Thanks

What I have tried:

Tried creating an observable collection but was not able to update the list.

解决方案

The sample below should work for a ListView - you can easily replace the listview with a listbox. Let me know if you have questions about it.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Collections.ObjectModel;

namespace ListViewTest.Test2
{
  public partial class ListViewTest : Window
  {
    /// <summary>
    /// ObservableCollection to store data displayed in listview
    /// </summary>
    ObservableCollection<GameData> _GameCollection = new ObservableCollection<GameData>();

    /// <summary>
    /// Standard Constructor fills up the ListView
    /// via Observable collection with three items
    /// </summary>
    public ListViewTest()
    {
      _GameCollection.Add(new GameData
      {
        GameName = "World Of Warcraft",
        Creator = "Blizzard",
        Publisher = "Blizzard"
      });

      _GameCollection.Add(new GameData
      {
        GameName = "Halo",
        Creator = "Bungie",
        Publisher = "Microsoft"
      });

      _GameCollection.Add(new GameData
      {
        GameName = "Gears Of War",
        Creator = "Epic",
        Publisher = "Microsoft"
      });

      InitializeComponent();
    }

    public ObservableCollection<GameData> GameCollection
    {
      get { return _GameCollection; }
    }

    /// <summary>
    /// Click button event adds a new element to the ObservableCollection
    /// each time the button is clicked -> the event is forwarded to listview
    /// which displays the change later on...
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void AddRow_Click(object sender, RoutedEventArgs e)
    {
      _GameCollection.Add(new GameData
      {
        GameName = "A New Game",
        Creator = "A New Creator",
        Publisher = "A New Publisher"
      });
    }
  }

  /// <summary>
  /// Simple class to be stored in ObservableCollection and to be displayed in Listview
  /// </summary>
  public class GameData
  {
    public string GameName { get; set; }
    public string Creator { get; set; }
    public string Publisher { get; set; }
  }
}



<Window x:Class="ListViewTest.Test2.ListViewTest"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   DataContext="{Binding RelativeSource={RelativeSource Self}}"

   Title="Some Game Data" Height="216" Width="435">

  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <TextBlock Grid.Row="0" TextWrapping="WrapWithOverflow" Margin="3">
    This smaple demonstates how to implment a ListView with static information in XAML (see ListView project)
    and how to populate information in a ListView via bound data source using an
    <TextBlock FontWeight="Bold">ObservableCollection</TextBlock>
     (see ListViewTest project).
    </TextBlock>

    <StackPanel Grid.Row="1">
      <ListView ItemsSource="{Binding GameCollection}">
        <ListView.View>
          <GridView>
            <GridViewColumn Width="140" Header="Game Name" DisplayMemberBinding="{Binding GameName}"  />
            <GridViewColumn Width="140" Header="Creator"   DisplayMemberBinding="{Binding Creator}" />
            <GridViewColumn Width="140" Header="Publisher" DisplayMemberBinding="{Binding Publisher}" />
          </GridView>
        </ListView.View>
      </ListView>
      <Button HorizontalAlignment="Right" Margin="5,5,5,5"

      Content="Add Row" Click="AddRow_Click" />
    </StackPanel>
  </Grid>
</Window>


@Dirk,

Please see below, I have tried to make a simple application highlighting the issue,
- Mainwindow creates an instance of MainViewModel which creates an instance of the TcpConnection class.
- The observable collection is created in the TcpConnection class
- data is added to the observable collection "_CanMessage" during testing
- however its is never updated to the bound Listview

I am not entirely sure about the binding names in the xaml so there could be the issue..

Please let me know if you have any further questions.


using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Net.Sockets;
using System.Threading;
using System.Windows;
using static SampleProj.MainViewModel;

namespace SampleProj
{
    public partial class MainWindow : Window
    {
        MainViewModel _main;
        public MainWindow()
        {
            InitializeComponent();
            _main = new MainViewModel();
            DataContext = _main;
        }

        private void Connect_Button_Click(object sender, RoutedEventArgs e)
        {
            _main.Client.Connect();
        }

        private void Start_Button_Click(object sender, RoutedEventArgs e)
        {
            byte[] data = { 42, 0, 17, 2, 0, 22, 0, 0, 22, 43 };
            _main.Client.Write(data);
        }
    }

    class MainViewModel : ObservableObject
    {
        public TcpConnection Client { get; private set; }

        public MainViewModel()
        {
            Client = new TcpConnection();
        }

        public class Message
        {
            public string CANMessage { get; set; }
        }
    }

    public class TcpConnection : ObservableObject
    {
        TcpClient client;
        Thread threadClientReceive;
        NetworkStream clientStream;

        ObservableCollection<Message> _CanMessage = new ObservableCollection<Message>();

        bool receiveThreadAlive = false;
        bool flagThreadRunning = false;
        bool clientIsConnected = false;

        string identifier = string.Empty;
        string data = string.Empty;

        public TcpConnection()
        {

        }

        public void Connect()
        {
            client = new TcpClient();
            var result = client.BeginConnect("192.168.0.1", 10000, null, null);
            var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(2));
            threadClientReceive = new Thread(new ParameterizedThreadStart(TcpReceive));
            flagThreadRunning = true;
            receiveThreadAlive = true;
            threadClientReceive.Start(client);

            if (!success)
            {
                throw new Exception();
            }

            if (client.Connected)
            {
                clientIsConnected = true;
            }
        }


        public void TcpReceive(object client)
        {
            string bitString = string.Empty;
            bool startBitFound = false;
            byte startBit = 42;
            byte stopBit = 43;
            List<byte> receiveDataList = new List<byte>();

            TcpClient tcpClient = (TcpClient)client;
            if (tcpClient.Connected)
            {
                clientStream = tcpClient.GetStream();
            }

            byte[] buffer = new byte[1024];
            while (flagThreadRunning)
            {
                int bytesRead = 0;
                try
                {
                    bytesRead = clientStream.Read(buffer, 0, buffer.Length);
                }
                catch { }

                if (bytesRead == 0)
                {
                    break;
                }

                for (int i = 0; i < buffer.Length; i++)
                {
                    if (buffer[i] == startBit)
                    {
                        startBitFound = true;
                    }

                    if (startBitFound)
                    {
                        receiveDataList.Add(buffer[i]);
                    }

                    if (buffer[i] == stopBit)
                    {
                        if (receiveDataList.Count == 0)
                            break;
                        else
                        {
                            string message = HexEncoding.ToString(receiveDataList.ToArray());
                            if (message.Length > 0)
                            {
                                _CanMessage.Add(new Message { CANMessage = message });
                            }
                            startBitFound = false;
                            receiveDataList.Clear();
                            break;
                        }

                    }
                }
            }
        }


        public void Write(byte[] data)
        {
            clientStream = client.GetStream();
            try
            {
                clientStream.Write(data, 0, data.Length);
            }
            catch
            {
            }
        }
    }

    public class HexEncoding
    {
        public HexEncoding()
        {

        }

        public static string ToString(byte[] bytes)
        {
            string hexString = "";

            for (int i = 0; i < bytes.Length; i++)
            {
                hexString += bytes[i].ToString("X2");
            }
            return hexString;
        }
    }


    public class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}






        <Window x:Class="SampleProj.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SampleProj"
        
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="525">
    <Grid Margin = "0,0,-6.6,-242.2" >
        < Button Name="conect" Content="Connect" HorizontalAlignment="Left" Margin="119,37,0,0" VerticalAlignment="Top" Width="75" Click="Connect_Button_Click"/>
        <Button Name = "start" Content="Start Session" HorizontalAlignment="Left" Margin="240,37,0,0" VerticalAlignment="Top" Width="100" Click="Start_Button_Click"/>

        <ListView ItemsSource = "{Binding Message}" Grid.ColumnSpan="5" Grid.Column="2" HorizontalAlignment="Left" Height="489" Margin="29.4,65.6,0,0" Grid.Row="2" Grid.RowSpan="11" VerticalAlignment="Top" Width="429">
            <ListView.View>
                <GridView>
                    <GridViewColumn Width = " 200" Header="Message" DisplayMemberBinding="{Binding CANMessage}" ></GridViewColumn>

                </GridView>
            </ListView.View>
        </ListView>

    </Grid>
</Window>


这篇关于使用inotifypropertychanged C#WPF更新包含多个字符串的文本框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆