Wie binden ObservableCollection mit Listbox in WPF
Ich würde gerne binden ObservableCollection
mit Listbox
im WPF-Anwendung. Also, wenn Elemente in der ObservableCollection
verändert werden, die die ListBox
update selbst.
Es ist ein public static ObservableCollection<Camera> extension = new ObservableCollection<Camera>();
im Klasse Kamera
Und die ListBox
ist in der Klasse MainWindow.xaml
Habe ich versucht, aber es funktioniert nicht:
Kamera-Klasse:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace HomeSecurity {
public class Camera : INotifyPropertyChanged {
public static readonly Regex AxisMacPattern = new Regex("00408[Cc][a-zA-Z0-9]{6}");
public string _IP;
public string IP {
get {
return _IP;
}
set {
if (_IP != value) {
_IP = value;
OnPropertyChanged("IP");
}
}
}
public string _HTTPPort;
public string HTTPPort {
get {
return _HTTPPort;
}
set {
if (_HTTPPort != value) {
_HTTPPort = value;
OnPropertyChanged("HTTP");
}
}
}
public string _MAC;
public string MAC {
get {
return _MAC;
}
set {
if (_MAC != value) {
_MAC = value;
OnPropertyChanged("MAC");
}
}
}
public string _ServiceName;
public string ServiceName {
get {
return _ServiceName;
}
set {
if (_ServiceName != value) {
_ServiceName = value;
OnPropertyChanged("ServiceName");
}
}
}
public string _FullName;
public string FullName {
get {
return _FullName;
}
set {
if (_FullName != value) {
_FullName = value;
OnPropertyChanged("FullName");
}
}
}
public string _HostName;
public string HostName {
get {
return _HostName;
}
set {
if (_HostName != value) {
_HostName = value;
OnPropertyChanged("HostName");
}
}
}
public Camera() { }
public Camera(string MAC) : this(null, null, MAC, null, null, null) { }
public Camera(string MAC, string ServiceName) : this(null, null, MAC, ServiceName, null, null) { }
public Camera(string IP, string HTTPPort, string MAC, string ServiceName, string FullName, string HostName) {
this.IP = IP;
this.HTTPPort = HTTPPort;
this.MAC = MAC;
this.ServiceName = ServiceName;
this.FullName = FullName;
this.HostName = HostName;
AddToExtension(this);
}
public static ObservableCollection<Camera> _extension = new ObservableCollection<Camera>();
//
public ObservableCollection<Camera> extension {
get { return _extension; }
set {
if (_extension != value) {
_extension = value;
OnPropertyChanged("extension");
}
}
}
private void OnPropertyChanged(string propertyName) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
//
public static void AddToExtension(Camera camera) {
_extension.Add(camera);
}
public static void RemoveFromExtension(Camera camera) {
_extension.Remove(camera);
}
public static Camera GetFromExtension(String MAC) {
foreach (Camera camera in _extension)
if (camera.MAC.Equals(MAC))
return camera;
return null;
}
public static void PrintExtension() {
foreach (Camera camera in _extension)
Console.WriteLine(camera);
}
public override string ToString() {
return "IP: " + IP + " HTTP Port: " + HTTPPort + " MAC: " + MAC + " Service Name: " + ServiceName + " FullName: " + FullName + " HostName: " + HostName;
}
}
}
XAML:
<Window x:Class="HomeSecurity.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:HomeSecurity"
Title="MainWindow" WindowState="Maximized" Loaded="Window_Loaded"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="8*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="1366" />
</Grid.ColumnDefinitions>
<Border BorderBrush="Red" BorderThickness="4" Grid.Column="1" Grid.Row="0">
<ListBox x:Name="CameraListBox"
ItemsSource="{Binding Path=Camera.extension}">
<ListBox.Resources>
<DataTemplate DataType="{x:Type local:Camera}">
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="5">
<TextBox Text="Hello World" />
</Border>
</DataTemplate>
</ListBox.Resources>
</ListBox>
</Border>
<Border BorderBrush="Green" BorderThickness="2" Grid.Column="1" Grid.Row="1">
<ScrollViewer >
<WrapPanel x:Name="VideoPanel" >
</WrapPanel>
</ScrollViewer>
</Border>
</Grid>
</Window>
MainWindow.xaml.cs:
using Bonjour;
namespace HomeSecurity {
///<summary>
///Interaction logic for MainWindow.xaml
///</summary>
public partial class MainWindow : Window, INotifyPropertyChanged {
public MainWindow() {
DataContext = this;
InitializeComponent();
// this.DataContext = this;
}
//
private Camera _camera;
public Camera Camera
{
get { return _camera; }
set
{
if (_camera != value)
{
_camera= value;
OnPropertyChanged("Camera");
}
}
}
///<summary>
///Raises the PropertyChanged notification in a thread safe manner
///</summary>
///<param name="propertyName"></param>
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
//
private void Window_Loaded(object sender, RoutedEventArgs e) {
createGUI();
}
private void createGUI() {
Console.WriteLine("dupa");
Scanner.ScanService();
// startListening();
//THIS CODE WON'T RUN BECAUSE Scanner.ScanService(); have frozen it
AddVideoStream("192.168.0.2");
AddVideoStream("192.168.0.2");
AddVideoStream("192.168.0.2");
}
private void startListening() {
Camera._extension.CollectionChanged += (s, e) => {
// CameraListBox.Items.Add(Camera.extension.Last());
};
}
//TEN
private void AddVideoStream(String sourceIP) {
int cols = 2;
int formsHostWidth = (int)(VideoPanel.ActualWidth / cols) - 4;
WindowsFormsHost formsHost = new WindowsFormsHost();
VideoStream videoStream = new VideoStream(sourceIP);
formsHost.Width = formsHostWidth;
formsHost.Height = videoStream.GetPrefferedHeight(formsHostWidth);
formsHost.Child = videoStream;
Border lineBorder = new Border();
lineBorder.BorderBrush = Brushes.Green;
lineBorder.BorderThickness = new Thickness(2);
lineBorder.Child = formsHost;
VideoPanel.Children.Add(lineBorder);
}
}
}
Wenn ich eine änderung Konstruktor in MAinWindow.xaml.cs
zu:
InitializeComponent();
Camera = new Camera();
DataContext = this;
Bekomme ich:
aber diese wird nicht aktualisiert, Daten... es sind die Daten aus der Zeit, wo das Kamera-Objekt eingefügt wurde in die Verlängerung.
- Meinst du sth so? stackoverflow.com/questions/8490533/...
- Sie könnten versuchen, hinzufügen einer dummy-Objekt und entfernen Sie es sofort. Aber ich bin mir nicht sicher, was genau Sie versuchen zu erreichen? Haben Sie sich überlegt, dass Ihre UI-begrenzt auf die INotifyPropertyChange der einzelnen Objekte in Ihrer Sammlung statt?
- Oh, Die Bindung ist gut. Ich habe ObservableCollection-Liste in der Klasse A und listBox in der Klasse B... wie binden Sie diese beiden?
- Nur legen Sie es auf die ListBox die ItemSource an deiner ObservableCollection ist, wird es hören, wenn Elemente Hinzugefügt/entfernt.
- Bitte die lok zu Bearbeiten. Das binding funktioniert nicht. Wenn ich einstellen will ItemSource gibt es nur
custom expression
odercreate data binding option
. Aber ich kann nicht findenCamera.extension
überall int den Menüs - Was
<ListBox x:Name="CameraListBox" ItemsSource="{Binding Path=Camera.extension}">
? Vorausgesetzt, Ihr DataContex ist richtig. Ich denke, dass das die richtige syntax, nicht auf meinem Arbeits-PC zwar. - Funktioniert es nicht(die syntax ist ok). Am Anfang des Programms wird der
Camera.extension
leer ist, dann die Elemente, die Hinzugefügt werden, nachdem eine kurze Zeit(Kameras werden erkannt, die in das lokale Netzwerk und das HinzugefügtCamera.extension
), und das listbox-update erforderlich. Wie Sie auf hinzufügen, um diese in xaml zu Benachrichtigen, dass die Sammlung geändert oder sth so? - Hat die Kamera die INotifyPropertyChanged implementieren (und die extension-Eigenschaft)? Wenn Sie nicht verbindlich sind, um einen null-Wert, und die UI nie aktualisiert, wenn die beobachtbaren Sammlung wird erstellt und zugewiesen-Erweiterung.
- Zu Beginn danke für Eure Hilfe. Ich Hinzugefügt, um den OP-code der Kamera-Klasse, die ich Hinzugefügt
: INotifyPropertyChanged
nach deinem letzten Kommentar, aber ich weiß nicht, wie es zu implementieren. - Die Erweiterung ist in der Hälfte der Klasse.
- Sie müssen realisieren, dass Sie (oder setzen Sie es vor
InitalizeComponent()
)- siehe meine Antwort auf das post - stackoverflow.com/questions/20664707/... - Ich habe:
DataContext = this;
im Hauptfenster.xaml.cs aber keine Wirkung. - Vielleicht bin ich der Verfolgung falsche Sache. Ich möchte Veränderung, die lisbox, wenn eine Eigenschaft eines einzelnen Objekts in der Erweiterung geändert werden
- Siehe meine Antwort - lassen Sie mich wissen, wenn das macht keinen Sinn.
- Ok, ich hab Sie ALLES, was Sie mir sagten. Der aktualisierte code ist in der original-post. Es gibt keine Ergebnisse in der listbox an alle. Weiß nicht, was zu tun sonst.
- Und wenn Sie können, schauen Sie bitte am Ende der post... gibt es einen Hinweis zu Ihrem Beitrag.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Die Sie nicht wollen, um eine statische Eigenschaft, es sei denn, Sie wirklich wollen, zu sein geteilt zwischen allen Instanzen der Klasse.
Wenn UI initialisiert Erweiterung wird null sein. So wird die Bindung setup auf null und nichts passiert. Was Sie tun müssen, ist lassen Sie Ihre Benutzeroberfläche kennen, bei der Erweiterung aktualisiert, so kann es hören, wenn neue Objekte Hinzugefügt werden. Macht das Sinn?
Deinem Beispiel oben, wird die Eigenschaft nicht aufrufen PropertyChangedEventArgs, wenn Erweiterung wird erstellt, so ist es eigentlich nicht hören, um zu Ihrer Sammlung.
Außerdem fügen Sie dem Konstruktor
DataContext = this
, und die INotifyPropertyChanged implementieren, die in Ihrem Fenster-Klasse auch. So etwasIch glaube, Sie brauchen, um eine Daten-Vorlage für etwas zu zeigen, bis zu
IP: 192.168.0.12 HTTP Port: 9080 MAC: 00408CBEEAE5 Service Name: AXIS M1011-W - 00408CBEEAE5 FullName: AXIS\032M1011-W\032-\03200408CBEEAE5._axis-video._tcp.local. HostName: axis-00408cbeeae5.local.
public ObservableCollection<Camera> extension; { get { return Camera.extension OR Camera._extension????; } set { if (_extension != value) { _extension= value; OnPropertyChanged("extension"); } } }
bin ich verlorenInitializeComponent(); this.Camera = new Camera(); this.DataContext = this;
im Hauptfenster Konstruktor. Aber ich bin in der gleichen Ort, den ich begann, als ich gebunden, die es durch die Veranstaltung.Camera._extension.CollectionChanged += (s, e) => { CameraListBox.Items.Add(Camera.extension.Last()); };
IP
,HTTPPort
,MAC
, und andere Eigenschaften in der Kamera-KlasseCamera._extension.CollectionChanged += (s, e) => { CameraListBox.Items.Add(Camera.extension.Last()); };
..., Wie zum implementieren dieser INotify im Hauptfenster : ( ?OnPropertyChanged("<PROPERTY NAME");
alle Zeit der änderung einer Eigenschaft.DataContext = this;
nachInitializeComponent()
Sie hinzufügen vor. Flüstern ist ok?InitializeComponent()
führt Ihre XAML, so müssen Sie Ihre Daten Kontext-setup bevor Sie dann sonst Ihre Bindung wird nicht wie beschrieben funktionieren.Versuchen, eine Eigenschaft, die zurück
extension
statisches Feld, dann binden Sie die ListBox zu dieser Eigenschaft. Soweit ich weiß, haben Sie zu binden-Eigenschaft, anstelle des Feldes.UPDATE :
Als ich sehen können, aktualisieren Sie setzen DataContext zu code-behind. Das bedeutet, Sie haben, um eine Eigenschaft mit dem Namen der Kamera im Hauptfenster.xaml.cs. Dann müssen Sie entweder die INotifyPropertyChanged implementieren, es zu initialisieren oder Kamera-Eigenschaft, bevor Sie die Einstellung der DataContex :
<ListBox x:Name="CameraListBox" ItemsSource="{Binding Path=Camera.bindableExtension}" />
im XAML-Code. Aber keine Wirkung. Muss ich etwas tunDataContext
oder dieseINotifyPropertyChanged
?Camera._extension.CollectionChanged += (s, e) => { CameraListBox.Items.Add(Camera.extension.Last()); };
Wenn das Objekt in die Kamera.- Erweiterung wird aktualisiert -> Feld geändert hat, passiert nichts.