调用 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 公共(public)类 MainViewModel :INotifyPropertyChanged { #region INotify 方法 公共(public)事件 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
}
}
最佳答案
您创建了 MainViewModel 的两个实例。每当您在 Stack Overflow 上看到“我的 View 模型中的所有内容都为空,但同时它不是”时,请在 XAML 和构造函数中查找重复的 View 模型实例化。
您莫名其妙地从 Window.Resources
中的一次性副本中获取命令,该副本没有用于其他用途。不要那样做。从这些绑定(bind)中删除 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}" />
关于c# - 调用命令方法时属性为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56173274/