Comment lier ObservableCollection avec Listbox dans WPF
Je voudrais lier ObservableCollection
avec Listbox
en application WPF. Ainsi, lorsque des éléments dans le ObservableCollection
sera modifié la ListBox
va se mettre à jour.
Il y a un public static ObservableCollection<Camera> extension = new ObservableCollection<Camera>();
dans Appareil photo de classe
Et la ListBox
est dans la classe MainWindow.xaml
J'ai essayé, mais il ne fonctionne pas:
Appareil photo de classe:
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);
}
}
}
Si je change de constructeur en MAinWindow.xaml.cs
à:
InitializeComponent();
Camera = new Camera();
DataContext = this;
J'obtiens:
mais ce n'est pas des données mises à jour... c'est des données de frome le moment où l'Appareil photo de l'objet a été inséré dans l'extension.
- Voulez-vous dire qqch comme ça? stackoverflow.com/questions/8490533/...
- Vous pourriez essayer d'ajouter un objet factice et l'enlever tout de suite. Mais je ne suis pas sûr exactement ce que vous essayez d'accomplir? Avez-vous envisagé d'avoir votre INTERFACE utilisateur délimitée à l'INotifyPropertyChange de l'individu objets de votre collection à la place?
- Oh Que la liaison est bonne. J'ai ObservableCollection liste dans la classe A et de la zone de liste dans la classe B... comment lier ces deux-là?
- Il suffit de le régler à la zone de liste de ItemSource à votre ObservableCollection, il sera à l'écoute lorsque des éléments sont ajoutés ou supprimés.
- Veuillez lok à le modifier. La liaison ne fonctionne pas. Quand je veux mettre ItemSource il y a seulement
custom expression
oucreate data binding option
. Mais je ne trouve pasCamera.extension
n'importe où int ces menus - Qu'en est
<ListBox x:Name="CameraListBox" ItemsSource="{Binding Path=Camera.extension}">
? En supposant que votre DataContex est correct. Je pense que c'est la bonne syntaxe, pas à mon PC de travail même si. - Il ne fonctionne pas(la syntaxe est ok). Au début du programme de la
Camera.extension
est vide, puis les éléments sont ajoutés après un court laps de temps(caméras sont détectés dans le réseau local et ajouté àCamera.extension
) et la zone de liste des besoins de mise à jour. Comment faire pour ajouter à ce xaml informer que la collecte changé ou qqch comme ça? - L'Appareil implémenter INotifyPropertyChanged (et l'extension de la propriété)? Si non, vous êtes la liaison à une valeur nulle, et votre INTERFACE utilisateur n'est jamais mis à jour lorsque de la collection observable est créé et associé à l'extension.
- Au début je vous remercie pour votre aide. J'ai ajouté à l'OP de code de l'Appareil photo de classe, j'ai ajouté
: INotifyPropertyChanged
après votre dernier commentaire, mais je ne sais pas comment la mettre en œuvre. - L'extension est à la moitié de la classe.
- Vous aurez besoin pour le mettre en œuvre (ou d'un ensemble avant
InitalizeComponent()
)- voir ma réponse sur ce post - stackoverflow.com/questions/20664707/... - J'ai fait:
DataContext = this;
dans MainWindow.xaml.cs, mais aucun effet. - Peut-être que je suis à la poursuite de quelque chose de mal. Je veux obtenir le changement de lisbox lorsqu'une propriété de l'objet unique dans cette extension sera changé
- Voir ma réponse - laissez-moi savoir si cela a un sens.
- Ok, je vous ai fait TOUT ce que vous m'avez dit. La mise à jour du code est dans le post original. Il n'y a pas de résultats dans la zone de liste à tous. Ne sais pas quoi faire d'autre.
- Et si vous pouvez s'il vous plaît regarder à la fin du post... il est fait référence à ton post.
Vous devez vous connecter pour publier un commentaire.
Vous ne souhaitez pas utiliser une propriété statique, sauf si vous voulez vraiment être partagée entre toutes les instances de la classe.
Lors de votre INTERFACE utilisateur est initialisé extension sera nulle. De sorte que la liaison sera le programme d'installation pour nulle et il ne se passera rien. Ce que vous devez faire est de laisser votre INTERFACE utilisateur de savoir quand l'extension est mis à jour, il peut écouter lorsque de nouveaux objets sont ajoutés. Cela fait-il sens?
Votre exemple ci-dessus, la propriété n'est pas l'appel de PropertyChangedEventArgs lorsque l'extension est créé de sorte qu'il n'est pas réellement à l'écoute de votre collection.
Également l'ajouter à votre constructeur
DataContext = this
, et implémenter INotifyPropertyChanged dans votre classe de fenêtre également. Quelque chose comme ceciJe pense que vous avez besoin d'avoir un modèle de données pour quelque chose à montrer trop
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"); } } }
je suis perduInitializeComponent(); this.Camera = new Camera(); this.DataContext = this;
dans la fenêtre principale du constructeur. Mais je suis dans le même endroit, j'ai commencé quand j'affectée par l'événement.Camera._extension.CollectionChanged += (s, e) => { CameraListBox.Items.Add(Camera.extension.Last()); };
IP
,HTTPPort
,MAC
, et d'autres propriétés de l'Appareil photo de classeCamera._extension.CollectionChanged += (s, e) => { CameraListBox.Items.Add(Camera.extension.Last()); };
..., Comment mettre en place cette INotify dans la fenêtre principale : ( ?OnPropertyChanged("<PROPERTY NAME");
tout moment toute modification de propriété.DataContext = this;
aprèsInitializeComponent()
vous ajoutez à cela avant. Whis on est ok?InitializeComponent()
exécute votre code XAML, de sorte que vous besoin de votre contexte de données de configuration avant, sinon votre liaison ne fonctionne pas comme à l'écrit.Essayez de créer une propriété que le retour
extension
champ statique, puis lier votre zone de liste pour cette propriété. Comme je sais que vous avez à se lier à la propriété plutôt que de champ.Mise à JOUR :
Que je peux voir à partir de la mise à jour vous définissez DataContext de code derrière. Cela signifie, vous devez créer une propriété nommée Caméra dans MainWindow.xaml.cs. Ensuite, vous devez implémenter INotifyPropertyChanged là ou l'initialisation de la Caméra de la propriété avant de la DataContex :
<ListBox x:Name="CameraListBox" ItemsSource="{Binding Path=Camera.bindableExtension}" />
en XAML. Mais aucun effet. Dois-je faire quelque chose à propos deDataContext
ou ceINotifyPropertyChanged
?Camera._extension.CollectionChanged += (s, e) => { CameraListBox.Items.Add(Camera.extension.Last()); };
Lorsque l'objet dans l'Appareil photo.l'extension est mis à jour -> champ a changé, rien ne se passe.