C# C:公共observablecollection实例将项目传递给受保护的observablecollection

C# C:公共observablecollection实例将项目传递给受保护的observablecollection,c#,mvvm,observablecollection,C#,Mvvm,Observablecollection,我上了下面的课,效果很好 public class RemoteSource { ObservableCollection<RemoteDataViewModel> remote; string[] _servers = new string[] { "server", "server", "server", "server", "server" }; public Rem

我上了下面的课,效果很好

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; }
}
我想通读一个文本文件,其中包含如下服务器名称列表

Server1
Server2
Server3
etc
然后将它们加载到一个ObservableCollection中,这样就可以做与我目前在这条线上做的相同的事情

foreach (var host in _servers) # but where _servers is the observablecollection initiated from the button event
我尝试在button事件下执行类似的操作,但是rs.hosts总是返回null

RemoteSource rs = new RemoteSource();
rs.hosts.Add(Environment.MachineName);
您的ObservableCollection应该是ViewModel的一个属性。然后,在视图中,将一些ItemsControl.ItemsSource属性绑定到它

例如,超级简化:

public class SessionViewModel : INotifyPropertyChanged
{
    // ...

    public ObservableCollection<String> ServerList { get; set; }
}
在我看来

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

不确定您是否试图让用户选择服务器或编辑服务器。我两个都回答。先编辑,然后选择

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

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

public sealed class ServerInfo
{
    public string Name {get;set;}
    public string IP {get;set;}
    public string Whatevs {get;set;}
}
在VM中,您将从ViewModel中公开服务器列表。如果您希望在选定的服务器上执行工作,则希望拥有选定的属性并在更新上执行工作

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和核心业务逻辑之间,而核心业务逻辑根本不应该关心UI。例如,连接到服务器与UI无关。标识要连接到的服务器不起作用。弥补这一差距的是虚拟机的作用。

我并没有试图bing到我已经更新了源代码的元素,这是一种代码味道。字符串实例是不可变的;绑定只能更改字符串的值;它不能用其他实例替换集合中的实例。记住,这是_M_VVM-MODEL视图ViewModel。从虚拟机中公开模型。这些模型的属性通过绑定进行更改。不要公开原语,尤其是不可变的结构/类。Hmmm。。。或者您只是想按服务器名称在服务器之间切换?无论如何,添加一个答案。。。
<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>