如何在WPF中将ObservableCollection与Listbox绑定

时间:2014-01-15 03:35:47

标签: c# events observablecollection

我想将ObservableCollectionListbox绑定在WPF应用程序中。因此,当ObservableCollection中的元素被修改时,ListBox将自行更新。

类相机

中有public static ObservableCollection<Camera> extension = new ObservableCollection<Camera>();

ListBox位于班级MainWindow.xaml

我试过了,但它不起作用:

enter image description here

相机类:

       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);

        }
    }
}

enter image description here

如果我将MAinWindow.xaml.cs中的构造函数更改为:

  InitializeComponent();
            Camera = new Camera();
            DataContext = this;

我明白了:

enter image description here

但这不是更新的数据...它是将数据对象插入扩展名的时间数据。

2 个答案:

答案 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>