MVVM:如何绑定到ListBox?

时间:2018-03-07 20:02:24

标签: c# xaml mvvm

正如您将注意到我是WPF-MVVM的新手。

我正在尝试构建一个简单的应用程序来理解基础知识。我几乎阅读了这里提出的所有问题以及其他网站上的一些问题。我似乎无法用给出的例子/答案来解释它。

首先是场景:

我想使用WMI从远程计算机获取信息。

在我的XAML上,我有两个用于计算机名称和WMI_Class的文本框(出于测试目的,我使用的是Win32_OperatingSystem,但希望最终可以使用不同的类

在我的项目中,我有以下文件夹: 查看 楷模 视图模型

我能够在没有MVVM部分的情况下获得我想要的所有信息。任何帮助,将不胜感激。我的代码如下所示。

XAML

<Window x:Class="RemoteComputerTest.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:RemoteComputerTest"
    xmlns:vm ="clr-namespace:RemoteComputerTest.ViewModels"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <StackPanel Grid.Column="0" Background="LightGray">
        <Label Content="Computer Name" />
        <TextBox x:Name="ComputerName" Width="100" Height="30" />
        <Label Content="Class Name" />
    <TextBox x:Name="ClassName"
                 Width="100"
                 Height="30" 
             Margin="0,10,0,0"/>

        <Button x:Name="Submit"
                Height="40"
                Width="60"
                Margin="0,20,0,0"
                Content="Submit"/>
    </StackPanel>
    <ListBox Grid.Column="1" Name="ListBox" Background="LightBlue">

    </ListBox>
</Grid>

我一直在玩那些可能没有意义的代码

模型

namespace RemoteComputerTest.Model
{
   public class sysInfo : INotifyPropertyChanged 
{
    private string _computerName;

    public string ComputerName
    {
        get { return _computerName; }
        set {_computerName = value; }
    }

    private string _className;

    public string ClassName
    {
        get { return _className; }
        set { _className = value; }
    }


    StringBuilder _result = new StringBuilder();

    public StringBuilder RemoteComputerInfoCustomized(string ComputerName)
    {

        _result.Clear();

        try
        {
            ManagementScope ManagementScope1 = new ManagementScope(string.Format("\\\\{0}\\root\\cimv2", ComputerName));
            ManagementScope1.Connect();
            ObjectGetOptions objectGetOptions = new ObjectGetOptions();
            ManagementPath managementPath1 = new ManagementPath(ClassName);
            ManagementClass ManagementClass1 = new ManagementClass(ManagementScope1, managementPath1, objectGetOptions);


            foreach (ManagementObject ManagementObject1 in ManagementClass1.GetInstances())
            {
                // Display the remote computer information
                this._result.Append(string.Format("Computer Name : {0}", ManagementObject1["csname"]));
                this._result.Append(string.Format("Windows Directory : {0}", ManagementObject1["WindowsDirectory"]));
                this._result.Append(string.Format("Operating System: {0}", ManagementObject1["Caption"]));
                this._result.Append(string.Format("Version: {0}", ManagementObject1["Version"]));
                this._result.Append(string.Format("Manufacturer : {0}", ManagementObject1["Manufacturer"]));
                this._result.Append(string.Format("Latest bootup time : {0}", ManagementObject1["LastBootUpTime"]));
            }
        }
        catch (Exception ex)
        {
            _result.Append(string.Format("Can't Connect to Computer: {0}\n{1}", ComputerName, ex.Message));
        }

        return _result;
    }



    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string p)
    {
        PropertyChangedEventHandler ph = PropertyChanged;
        if (ph != null)
            ph(this, new PropertyChangedEventArgs(p));
    }
    }
}

就ViewModel而言,我真的不知道调用什么或如何调用它并将其写入xaml中的列表框。代码可能是一团糟,我道歉已经为此工作了几天没有而且无处可去!

视图模型

namespace RemoteComputerTest.ViewModels
{
   public class sysInfoVM : INotifyPropertyChanged
    {

    private sysInfo _getremotecomputer;
    public StringBuilder results;

   //giving error "must have a return type 
   public RemoteComputerVM(string compName, StringBuilder RST ) 
    {
        _result = RST;
        _getremotecomputer = new sysInfo();
        _getremotecomputer.ComputerName = "TEST-DESKTOP";

        return _results; //error here "because viewmodel returns void keyword must not be followed with an object. Which I don't have void? 


    }


    private StringBuilder Results;

    public StringBuilder _results
    {
        get { return Results; }
        set { _results = value; OnPropertyChanged("Results"); }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string p)
    {
        PropertyChangedEventHandler ph = PropertyChanged;
        if (ph != null)
            ph(this, new PropertyChangedEventArgs(p));
        }
    }

   }

1 个答案:

答案 0 :(得分:0)

这是最简单的入门示例,应该是自我解释的:

XAML:

<Window
    x:Class="WpfApp1.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:local="clr-namespace:WpfApp1"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainWindow"
    Width="525"
    Height="350"
    d:DataContext="{d:DesignInstance local:Model}"
    mc:Ignorable="d">
    <Window.DataContext>
        <local:Model />
    </Window.DataContext>
    <StackPanel>
        <Button
            Command="{Binding UpdateText}"
            Content="Update text" />
        <ListBox ItemsSource="{Binding Collection}" />
    </StackPanel>
</Window>

型号:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.CompilerServices;

namespace WpfApp1
{
    internal class Model : INotifyPropertyChanged
    {
        private ObservableCollection<string> _collection;

        public Model()
        {
            UpdateText = new RelayCommand(UpdateTextExecute);
            Collection = new ObservableCollection<string>();
        }

        public RelayCommand UpdateText { get; }

        public ObservableCollection<string> Collection
        {
            get => _collection;
            set
            {
                _collection = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void UpdateTextExecute(object s)
        {
            var text = DateTime.Now.ToString(CultureInfo.InvariantCulture);
            Collection.Add(text);
        }

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

命令:

using System;
using System.Windows.Input;

namespace WpfApp1
{
    public class RelayCommand : ICommand
    {
        private readonly Func<object, bool> _canExecute;
        private readonly Action<object> _execute;

        public RelayCommand(Action<object> execute) : this(execute, s => true)
        {
        }

        public RelayCommand(Action<object> execute, Func<object, bool> canExecute)
        {
            _execute = execute;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute(parameter);
        }

        public void Execute(object parameter)
        {
            _execute(parameter);
        }

        public event EventHandler CanExecuteChanged
        {
            add => CommandManager.RequerySuggested += value;
            remove => CommandManager.RequerySuggested -= value;
        }
    }
}

现在去查看你不了解的文件。