我想将ObservableCollection
与Listbox
绑定在WPF应用程序中。因此,当ObservableCollection
中的元素被修改时,ListBox
将自行更新。
类相机
中有public static ObservableCollection<Camera> extension = new ObservableCollection<Camera>();
ListBox
位于班级MainWindow.xaml
我试过了,但它不起作用:
相机类:
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);
}
}
}
如果我将MAinWindow.xaml.cs
中的构造函数更改为:
InitializeComponent();
Camera = new Camera();
DataContext = this;
我明白了:
但这不是更新的数据...它是将数据对象插入扩展名的时间数据。
答案 0 :(得分:2)
尝试创建一个返回extension
静态字段的属性,然后将ListBox绑定到该属性。据我所知,你必须绑定到属性而不是字段。
public static ObservableCollection<Camera> extension = new ObservableCollection<Camera>();
public ObservableCollection<Camera> bindableExtension
{
get { return extension; }
}
更新:
正如我从更新中看到的那样,您将DataContext设置为后面的代码。这意味着,您必须在MainWindow.xaml.cs中创建名为Camera的属性。然后你必须在那里实现INotifyPropertyChanged或者在设置DataContex之前初始化Camera属性:
public MainWindow() {
InitializeComponent();
this.Camera = new Camera();
this.DataContext = this;
}
...
public Camera Camera { get; set; }
答案 1 :(得分:2)
除非您真的希望在班级的所有实例之间共享,否则您不想使用静态属性。
初始化UI时,扩展名为null。因此绑定将设置为null并且不会发生任何事情。您需要做的是让您的UI知道何时更新扩展,以便它可以监听添加新对象的时间。这有意义吗?
上面的示例中,在创建扩展名时,该属性不会调用PropertyChangedEventArgs,因此它实际上并未侦听您的集合。
public class Camera : INotifyPropertyChanged
{
private ObservableCollection<Camera> _extension;
public ObservableCollection<Camera> extension;
{
get { return _extension; }
set
{
if (_extension != value)
{
_extension= value;
OnPropertyChanged("extension");
}
}
}
/// <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
}
还要将其添加到构造函数DataContext = this
中,并在窗口类中实现INotifyPropertyChanged。像这样的东西
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow() {
DataContext = this;
InitializeComponent();
}
// ...
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
}
我认为你需要有一个数据模板来显示某些东西
<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>