DataGridTemplateColumn 更新

DataGridTemplateColumn update

我正在将一个旧控件改写为 WPF。我需要制作一个显示警报列表的数据网格。数据网格的第一列是一个数据网格模板列,其中包含一个标志图标和日期。当用户按下按钮时,警报被确认并且标志图标必须消失。我正在使用 MVVM 模式。

问题是我似乎无法更新 datagridtemplate 列中的标志。当我将确认状态从 0 更改为 1(警报已确认)时,该标志不会消失。当我重新加载控件并再次从服务器获取警报时,该标志不再显示,表明其状态实际上已在服务器中更新。所以我的代码以某种方式工作但我的 UI 没有更新。我还尝试以相同的方式更改警报的描述,并且该列确实得到了更新。 (MainViewModelBase 实现 INotifyPropertyChanged)

风景

<DataGrid x:Class="Kwa.Presentation.Views.AlarmList.AlarmList"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          xmlns:local="clr-namespace:Kwa.Presentation.Views.AlarmList"
          xmlns:components="clr-namespace:Kwa.Presentation.Components"
          xmlns:converters="clr-namespace:Kwa.Presentation.Converters"
          xmlns:Trans="clr-namespace:Kwa.Presentation.Resources"
          mc:Ignorable="d" 
          d:DesignHeight="500" d:DesignWidth="750"
          ItemsSource="{Binding Alarms}"
          SelectedItem="{Binding SelectedAlarm}"
          IsSynchronizedWithCurrentItem="True"
          CanUserResizeColumns="True" IsReadOnly="True" CanUserReorderColumns="False" CanUserSortColumns="False" SelectionMode="Single" CanUserAddRows="False"
          Background="White" RowHeaderWidth="0" AutoGenerateColumns="False" GridLinesVisibility="None" RowHeight="{Binding Rowheight}" FrozenColumnCount = "1"
          ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto"
          x:Name="AlarmFramework"
          SizeChanged="AlarmFramework_SizeChanged"
          >

    <DataGrid.Resources>
        <converters:AlarmSeverityToColorConverter x:Key="AlarmSeverityToColorConverter"/>
        <converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
        <converters:InvertedBoolToVisibilityConverter x:Key="InvertedBoolToVisibilityConverter"/>
</DataGrid.Resources>

    <DataGrid.Columns>

        <DataGridTemplateColumn Header="{x:Static Trans:TranslatedResources.AlarmColumnHeaderTime}" Width="auto" HeaderStyle="{StaticResource WithButt}">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <components:FlagControl VerticalAlignment="Center" Height="15" Width="15" FlagColor="{Binding Severity, Converter={StaticResource AlarmSeverityToColorConverter}}"
                                                Visibility="{Binding AckStatus, Converter={StaticResource InvertedBoolToVisibilityConverter}, Mode=TwoWay}"/>
                        <TextBlock Text="{Binding DateTimeString}" Padding="10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                    </StackPanel>

                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>

        <DataGridTextColumn Header="{x:Static Trans:TranslatedResources.AlarmColumnHeaderSeverity}" Binding="{Binding SeverityString}" Width="auto" HeaderStyle="{StaticResource WithoutButt}"/>

        <DataGridTextColumn Header="{x:Static Trans:TranslatedResources.AlarmColumnHeaderDescription}" Binding="{Binding Description}"  d:Width="400" Width="*" HeaderStyle="{StaticResource WithoutButt}"/>



    </DataGrid.Columns>
</DataGrid>

AlarmList 视图模型

public class AlarmListViewModel : MainViewModelBase
{
#region Properties
    private ObservableCollection<AlarmEntryViewModel> _alarms = new ObservableCollection<AlarmEntryViewModel>();
    public ObservableCollection<AlarmEntryViewModel> Alarms
    {
        get { return _alarms; }
        set
        {
            _alarms = value;
            RaisePropertyChanged(() => Alarms);
        }
    }

    private AlarmEntryViewModel _selectedAlarm;
    public AlarmEntryViewModel SelectedAlarm
    {
        get { return _selectedAlarm; }
        set
        {
            _selectedAlarm = value;
            RaisePropertyChanged(() => SelectedAlarm);
        }
    }

    private int _acknowledgeAllowed;
    public int AcknowledgeAllowed
    {
        get { return _acknowledgeAllowed; }
        set
        {
            _acknowledgeAllowed = value;
            RaisePropertyChanged(() => AcknowledgeAllowed);
        }
    }


    private readonly IActionCommand _acknowledgeCommand;
    public IActionCommand AcknowledgeCommand
    {
        get { return _acknowledgeCommand; }
    }

    public int MaxAcknowledgedAlarm;
    public double RowHeight { get; set; }
    public AlarmEntryViewModel AlarmToSend { get; set; }

    #endregion

    #region Constructor

    public AlarmListViewModel()
    {
        if (!IsInDesignMode)
        {
            RowHeight = 30;
        }

        //Add command
        _acknowledgeCommand = new ActionCommand<double>(p => Acknowledge(p));

    }

    #endregion

 #region Private Methods

        private void Acknowledge(double parameter)
        {
            if (AcknowledgeAllowed == 1)
            {
                try
                {
                    //Get Datagrid width
                    double DatagridWidth = (double)parameter;
                    //Calculate the amount of fully visible alarms
                    int AmountVisible = (int)Math.Floor(DatagridWidth / RowHeight);
                    if (Alarms.Count < AmountVisible)
                    {
                        AlarmToSend = Alarms[Alarms.Count - 1];
                        foreach(AlarmEntryViewModel alarm in Alarms)
                        {
                            alarm.AckStatus = true;
                            alarm.Description = "Iets nieuw";
                        }
                    }
                    else
                    {
                        //Send the last visible alarm, 0 based => -1
                        AlarmToSend = Alarms[AmountVisible - 1];
                        //Go to next visible alarm
                        SelectedAlarm = Alarms[AmountVisible];
                    }
                    //Acknowledge alarms
                    _proxy.Send(AlarmToSend.AlarmNumber);

                }
                catch (Exception ex)
                {
                    _viewManager.ShowDialog(new MessageDialogViewModel()
                    {
                        AskAnswer = false,
                        Text = ex.Message,
                        Title = TranslatedResources.AlarmAckSendErrorTitle,
                    });
                }
            }
            else
            {
                _viewManager.ShowDialog(new MessageDialogViewModel()
                {
                    AskAnswer = false,
                    Text = TranslatedResources.AlarmAcknErrorMessage,
                    Title = TranslatedResources.AlarmAcknErrorTitle,
                });
            }


        }

        #endregion

AlarmListEntry 视图模型

public class AlarmEntryViewModel : MainViewModelBase
    {
    #region Fields
    private readonly IViewManager _viewManager;
    private readonly IDockManager _dockManager;
    private string _description;

    #endregion

    #region Constructor

    public AlarmEntryViewModel()
    {
    }

    #endregion

    #region Model & Proxy

    private Alarm _model;
    public Alarm Model
    {
        set { _model = value; }
    }

    public AlarmListServiceProxy Proxy { get; set; }

    #endregion

    #region Properties

    public DateTime Time { get { return _model.Time; } }

    public string DateTimeString { get { return _model.Time.ToString("dd/MM/yyyy hh:mm:ss"); } }

    public int Severity { get { return _model.Severity; } }

    public string SeverityString
    {
        get
        {
            if (_model.Severity == 0)
                return "Melding";
            if (_model.Severity == 1)
                return "Waarschuwing";
            if (_model.Severity == 2)
                return "Fout";
            else
                return "Niet gekend";
        }
    }

    public string Description 
    { 
        get
        {
            //string substring = _model.Description.Substring(_model.Description.Length - 1);
            //if ( substring.Equals("\n"))
            //{
            //    return _model.Description.Substring(0, _model.Description.Length - 1);
            //}
            //else
            //    return _model.Description;
            return _description;
        }
        set
        {
            _description = value;
            RaisePropertyChanged(() => Description);
        }
    }

    public int AlarmNumber { get { return _model.Number; } }

    public int AcknStatus { get { return _model.AcknStatus; } }

    private bool _ackStatus;
    public bool AckStatus
    {
        get
        {
            if (_model.AcknStatus == 0)
                return false;
            else
                return true;

        }
        set
        {
            _ackStatus = value;
            RaisePropertyChanged(() => AckStatus);
        }
    }

    #endregion


}

您在 setter 中设置了 _ackStatus,但没有 return 来自 AlarmEntryViewModel 中 getter 的该字段的值。这样做:

private bool _ackStatus;
public bool AckStatus
{
    get
    {
        return _ackStatus;
    }
    set
    {
        _ackStatus = value;
        RaisePropertyChanged(() => AckStatus);
    }
}

或者在setter中设置_model.AcknStatus字段:

private bool _ackStatus;
public bool AckStatus
{
    get
    {
        if (_model.AcknStatus == 0)
            return false;
        else
            return true;

    }
    set
    {
        _ackStatus = value;
        _model.AcknStatus = value ? 1 : 0;
        RaisePropertyChanged(() => AckStatus);
    }
}