C#:public observablecollection <viewmodel>实例将项传递给protected observablecollection <viewmodel> </viewmodel> </viewmodel>

时间:2014-11-29 01:31:34

标签: c# mvvm observablecollection

我有以下课程可以正常使用

public class RemoteSource {
    ObservableCollection<RemoteDataViewModel> remote;
    string[] _servers = new string[] {
        "server",
        "server",
        "server",
        "server",
        "server"
    };
    public RemoteSource() {
        remote = CreateDataSource();
    }
    protected ObservableCollection<RemoteDataViewModel> CreateDataSource() {
        ObservableCollection<RemoteDataViewModel> res = new ObservableCollection<RemoteDataViewModel>();
        ITerminalServicesManager _manager = new TerminalServicesManager();
        foreach (var host in _servers) {
            using (ITerminalServer srv = _manager.GetRemoteServer(host)) {
                try {
                    srv.Open();
                    foreach (ITerminalServicesSession session in srv.GetSessions()) {
                        res.Add(new RemoteDataViewModel() { Server = srv.ServerName, SessionID = session.SessionId, UserID = session.UserName, State = session.ConnectionState, ConnectedTime = session.ConnectTime, LogonTime = session.LoginTime, IdleTime = session.IdleTime, UserIP = session.ClientIPAddress, Workstation = session.WindowStationName });
                    }
                    srv.Close();
                }
                catch (Win32Exception) { }
                catch (SystemException) { }
                catch (Exception) { }
            }
        }
        return res;
    }
    /// <summary>
    /// Gets the data.
    /// </summary>
    /// <value>
    /// The data.
    /// </value>
    public ObservableCollection<RemoteDataViewModel> Data { get { return remote; } }
    public ObservableCollection<string> hosts { get; set; }
}

RemoteSource已设置但是按钮事件执行以下操作

DataContext = new RemoteSource();

我想通读一个文本文件,其中包含服务器名称列表,如此

Server1
Server2
Server3
etc

并将它们加载到ObservableCollection中,然后能够执行我目前在此行上执行的操作

foreach (var host in _servers) # but where _servers is the observablecollection initiated from the button event

我尝试在按钮事件下执行类似的操作,但rs.hosts始终返回null

RemoteSource rs = new RemoteSource();
rs.hosts.Add(Environment.MachineName);

2 个答案:

答案 0 :(得分:1)

您的ObservableCollection<T>应该是ViewModel的属性。然后,在视图中,将一些ItemsControl.ItemsSource属性绑定到它。

例如(超简化):

public class SessionViewModel : INotifyPropertyChanged
{
    // ...

    public ObservableCollection<String> ServerList { get; set; }
}

在视图中

<ListView x:Name="ServerList" ItemsSource="{Binding ServerList}"/>

答案 1 :(得分:1)

不确定您是否尝试让用户选择服务器或编辑服务器。我正在回答这两个问题。先编辑,然后再选择。

绑定只能更新类的属性。它们不能用集合中另一种类型的完全不同的实例替换一种类型的实例。这不是它的工作原理。请记住,这是 模型查看ViewModel 。您的ViewModel必须公开 Models ,其属性绑定到UI中的元素。这些属性将由绑定更新。

因此,为您的服务器创建一个模型

public sealed class ServerInfo
{
    public string Name {get;set;}
    public string IP {get;set;}
    public string Whatevs {get;set;}
}

在您的VM中,您将从ViewModel公开您的服务器列表。如果您希望在选定的服务器上工作,您需要具有Selected属性并进行更新。

public sealed class ViewModelLol : INotifyPropertyChanged
{
    // init from ctor
    public ObservableCollection<ServerInfo> Servers {get;private set;}
    public ServerInfo SelectedServer {get;set;} // should be INPC impl, but yawn
    // boring stuff goes here
}

在您的UI中,您将ItemsSource绑定到集合

<ListBox ItemsSource="{Binding Servers}" SelectedItem="{Binding SelectedServer}" >
    <ListBox.ItemTemplate>
      <DataTemplate>
        <!-- If you wanted to edit the server name... -->
        <TextBox Text="{Binding Name}"/>
        <!-- If you only care about selection... -->
        <Label Content="{Binding Name}"/>    
      </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

不确定您是否希望能够编辑服务器名称,如果是,请使用第一个选项。如果要向用户显示服务器列表并允许他们选择一个,请使用标签选项。

用户选择服务器后,ViewModel中的SelectedServer会更新。您可以利用这个机会做您需要的任何工作。

ViewModels应该位于逻辑食物链的顶端。它们解释系统用户的操作并将其转换为API调用。因此,如果您需要连接到服务器,则VM应包含连接到服务器的逻辑。 VM不应该是某个业务逻辑类的子代。这需要一些棘手的意大利面条代码,并且将更难实现。

虚拟机应该位于用户界面和核心业务逻辑之间,根本不应该关心用户界面。例如,连接到服务器与UI无关。确定要连接的服务器。缩小差距是VM的作用。