Свойства являются нулевыми при вызове метода команды - PullRequest
1 голос
/ 16 мая 2019

Когда вызывается RefreshServices(), оба значения SelectedComputer и SelectedCustomer равны нулю, даже если их нет, когда я их на самом деле выбираю.

Почему?

/ edit: Forgotопубликовать объявления кнопок в 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
    }
}

1 Ответ

4 голосов
/ 16 мая 2019

Вы создали два экземпляра MainViewModel. Всякий раз, когда вы видите, что «все в моей модели представления является нулевым, хотя в то же время это не так» в Переполнении стека, ищите дублирующиеся экземпляры модели представления в XAML и конструкторе.

Вы получаете необъяснимым образом команды из одноразовой копии в Window.Resources, которая используется ни для чего другого. Не делай этого. Удалите Source={StaticResource viewModel} из этих привязок, и я думаю, что они должны работать, как они есть.

Сетка является прямым потомком окна и не имеет собственного 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}" />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...