调用RefreshServices()
时,SelectedComputer
和SelectedCustomer
都为空,即使我实际选择它们时都不为空。
为什么?
/ edit:忘记在XAML中发布按钮的声明。现在已更新。
MainWindow.xaml.cs
public partial class MainWindow : Window
{
MainViewModel _main = new MainViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = _main;
}
}
XAML:
<Window.Resources>
<vm:MainViewModel x:Key="viewModel" />
</Window.Resources>
<Border Margin="10">
<Grid>
<!-- Comboboxes -->
<GroupBox Header="Computer" Grid.Column="0" Grid.ColumnSpan="4" Margin="0 0 4 4">
<ComboBox ItemsSource="{Binding ComputerNames}"
SelectedItem="{Binding SelectedComputer}"
IsSynchronizedWithCurrentItem="True"
SelectedIndex="0"/>
</GroupBox>
<GroupBox Header="Customer" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="4" Margin="0 0 4 4" >
<ComboBox ItemsSource="{Binding CustomerNames}"
SelectedItem="{Binding SelectedCustomer}"
IsSynchronizedWithCurrentItem="True"
SelectedIndex="0"/>
</GroupBox>
<!-- Main list -->
<DataGrid x:Name="dataGrid" Grid.Row="2" Grid.ColumnSpan="8"
ItemsSource="{Binding Path=Services, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"
AutoGenerateColumns="False"
IsReadOnly="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Width="*" Binding="{Binding DisplayName}"/>
<DataGridTextColumn Header="Status" Width="*" Binding="{Binding Status}" />
<DataGridTextColumn Header="Machine Name" Width="*" Binding="{Binding MachineName}" />
</DataGrid.Columns>
</DataGrid>
<!-- Buttons-->
<Button Grid.Row="5" Grid.Column="0" Margin="0 4 4 4" Content="Start"
Command="{Binding Path=StartServiceCommand, Source={StaticResource viewModel}}"
CommandParameter="{Binding SelectedItems, ElementName=dataGrid}"/>
<Button Grid.Row="5" Grid.Column="1" Margin="4 4 0 4" Content="Stop"
Command="{Binding Path=StopServiceCommand, Source={StaticResource viewModel}}"
CommandParameter="{Binding SelectedItems, ElementName=dataGrid}"/>
<Button Grid.Row="5" Grid.Column="3" Margin="4 4 0 4" Content="Refresh"
Command="{Binding Path=RefreshServicesCommand, Source={StaticResource viewModel}}" />
</Grid>
</Border>
MainViewModel.cs 公共类MainViewModel:INotifyPropertyChanged { #region INotify方法 公共事件PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
#endregion
/*---------------------------- C U S T O M E R S -----------------------------*/
#region Customer Properties
private string _selectedCustomer;
private ObservableCollection<string> _customerNames;
public string SelectedCustomer
{
get => _selectedCustomer;
set
{
SetField(ref _selectedCustomer, value);
Services = Utils.UpdatedServices(SelectedComputer, SelectedCustomer);
}
}
public ObservableCollection<string> CustomerNames
{
get => _customerNames;
set
{
SetField(ref _customerNames, value);
Services = Utils.UpdatedServices(SelectedComputer, SelectedCustomer);
}
}
#endregion
/*---------------------------- S E R V I C E S -----------------------------*/
#region Services Properties
private ObservableCollection<ServiceController> _services;
private ObservableCollection<ServiceController> _selectedServices;
public ObservableCollection<ServiceController> SelectedServices
{
get => _selectedServices;
set => SetField(ref _selectedServices, value);
}
public ObservableCollection<ServiceController> Services
{
get => _services;
set => SetField(ref _services, value);
}
#endregion
/*---------------------------- C O M P U T E R S -----------------------------*/
#region Computer Properties
private string _selectedComputer;
private ObservableCollection<string> _computerNames;
public string SelectedComputer
{
get => _selectedComputer;
set
{
SetField(ref _selectedComputer, value);
CustomerNames = Utils.UpdatedCustomerNames(SelectedComputer);
}
}
public ObservableCollection<string> ComputerNames
{
get => _computerNames;
set => SetField(ref _computerNames, value);
}
#endregion
/*---------------------------- C O M M A N D S -----------------------------*/
#region Commands
public StartServiceCommand StartServiceCommand { get; set; }
public void StartService(ObservableCollection<ServiceController> serviceControllers)
{
try
{
foreach(var service in serviceControllers)
if (service.Status != ServiceControllerStatus.Running)
service.Start();
RefreshServices();
}
catch (Exception ex) { }
}
public StopServiceCommand StopServiceCommand { get; set; }
public void StopService(ObservableCollection<ServiceController> serviceControllers)
{
try
{
foreach (var service in serviceControllers)
if (service.Status != ServiceControllerStatus.Stopped &&
service.Status != ServiceControllerStatus.StopPending)
service.Stop();
RefreshServices();
}
catch (Exception ex) { }
}
public RefreshServicesCommand RefreshServicesCommand { get; set; }
public void RefreshServices()
{
Services = Utils.UpdatedServices(SelectedComputer, SelectedCustomer);
}
#endregion
public MainViewModel()
{
#region Initialize
_services = new ObservableCollection<ServiceController>();
_computerNames = new ObservableCollection<string>();
_customerNames = new ObservableCollection<string>();
_selectedComputer = _customerNames.FirstOrDefault();
_selectedServices = new ObservableCollection<ServiceController>();
ComputerNames = new ObservableCollection<string> { Environment.MachineName, Environment.MachineName };
StartServiceCommand = new StartServiceCommand(this);
StopServiceCommand = new StopServiceCommand(this);
RefreshServicesCommand = new RefreshServicesCommand(this);
#endregion
}
}
答案 0 :(得分:4)
您创建了MainViewModel的两个实例。每当您在Stack Overflow上看到“即使同时没有,我的viewmodel中的所有内容都为空时”,则在XAML和构造函数中查找重复的viewmodel实例。
您莫名其妙地从Window.Resources
的一次性副本中获取了Commands,该副本没有其他用途。不要那样做从这些绑定中删除Source={StaticResource viewModel}
,我认为它们应该按原样工作。
Grid是Window的直接子级,并且没有自己的DataContext,所以应该没问题。让我知道是否。我们可以使它正常工作而不会带来太多麻烦。
<Button Grid.Row="5" Grid.Column="0" Margin="0 4 4 4" Content="Start"
Command="{Binding StartServiceCommand}"
CommandParameter="{Binding SelectedItems, ElementName=dataGrid}"/>
<Button Grid.Row="5" Grid.Column="1" Margin="4 4 0 4" Content="Stop"
Command="{Binding StopServiceCommand}"
CommandParameter="{Binding SelectedItems, ElementName=dataGrid}"/>
<Button Grid.Row="5" Grid.Column="3" Margin="4 4 0 4" Content="Refresh"
Command="{Binding RefreshServicesCommand}" />