我正在编写一个应用程序来阅读和分析我公司软件使用的一些日志。有多种类型的日志,但为了描述我的问题,我们只需要两个。即,TypeA
和TypeB
的日志。我设计了一个类来保存一行日志数据,名为LogLine
,如下所示。
public class LogLine
{
public long LineNum { get; set; }
public string Msg { get; set; }
}
所以这是我的问题/要求。
在我的主ViewModel
中,我想在应用程序加载时只读取每种类型的日志一次。一次阅读TypeA
个日志,并存储在ObservableCollection
LogLine
个实例中,对TypeB
执行相同操作。然后根据我的选择,DataGrid
显示来自一种类型的日志,如果我在任何时候单击一个按钮,则相同的DataGrid
应该显示来自另一种类型的日志。请注意,我的日志数据没有变化,我只想显示我选择的日志。
为此,我创建了三个类,即ControllerMain
,ControllerA
和ControllerB
。最后两个来自前者,如此:
public class ControllerMain
{
public ControllerMain()
{
LogLineList = new ObservableCollection<LogLine>();
}
private ObservableCollection<LogLine> logLineList;
public ObservableCollection<LogLine> LogLineList
{
get { return logLineList; }
set { logLineList = value; }
}
}
public class ControllerA : ControllerMain
{
public ControllerA() { }
// More stuff here
}
public class ControllerB : ControllerMain
{
public ControllerB() { }
// More stuff here
}
您可以猜测ControllerA
旨在保存TypeA
的日志,以及这些日志特有的关联属性和方法。 TypeB
日志也是如此。
在我的ViewModel
中,我有上面每个类的实例,并且在应用程序加载时,我读取日志数据并存储在适当的类对象中。
public ControllerMain COMMON_LOG { get; set; }
public ControllerA A_LOG { get; set; }
public ControllerB B_LOG { get; set; }
public ViewModelMain()
{
isAType = true;
ClickCommand = new CustomCommand(ClickCmd, CanClickCmd);
A_LOG = new ControllerA
{
// This simulates reading logs from files - done only once
LogLineList = DataService.GetAData()
};
B_LOG = new ControllerB
{
// This simulates reading logs from files - done only once
LogLineList = DataService.GetBData()
};
// This simulates switching to already loaded logs.
// When I do this the log lines don't change, but I want to refresh the datagrid and display correct info.
LoadAppropriateLog();
}
private void LoadAppropriateLog()
{
if (isAType)
{
COMMON_LOG = A_LOG;
isAType = false;
}
else
{
COMMON_LOG = B_LOG;
isAType = true;
}
}
我的View
绑定到COMMON_LOG
实例,如下所示:
<DataGrid Grid.Row="0" Margin="5"
Name="dgLogs"
AutoGenerateColumns="False" SelectionUnit="CellOrRowHeader"
ItemsSource="{Binding COMMON_LOG.LogLineList}">
然后,只需点击一下按钮,我就会调用上面的LoadAppropriateLog()
方法,因此它只会将适当类型的实例分配给COMMON_LOG
,这是我用于数据的实例绑定。
问题在于,当我这样做时,由于每个实例LogLineList
中的实际数据都没有变化,DataGrid
不会自动更新以反映我选择的日志。
每次切换日志类型后,有没有办法从DataGrid
手动刷新ViewModel
?
如果您想运行该项目,请参阅下面的链接:
答案 0 :(得分:2)
如果你在XAML中绑定了一个类的属性,那么
INotifyPropertyChanged
,该属性应在其setter中引发PropertyChanged
。 在您的情况下,您正在更改COMMON_LOG
的值,并且您永远不会更改其LogLineList
的值。
tl; dr:因此,您的主视图模型需要实现INotifyPropertyChanged
,并在PropertyChanged
的设置器中引发COMMON_LOG
。任何不做的事情那些东西不是视图模型。
LogLineList
的 ObservableCollection
将无法完成任何操作:该类所做的是在添加,删除或替换项目时发出通知。在绑定看到它之后的任何时候都不会发生这种情况。那些ObservableCollection
的实例甚至不知道主视图模型甚至存在,因此当它们的属性发生变化时,它们肯定不会引发通知事件。它们也不应该:每个人都对自己的通知负责。
事实上,如果您做出设计决定,初始化后这些集合永远不会更改,请使用ReadOnlyCollection
代替ObservableCollection
。创建一个很简单:致电List<T>.AsReadOnly<T>()
。对于任何IEnumerable<T>
,只需致电e.ToList().AsReadOnly()
即可。 ObservableCollection
表示“你可以添加内容”。但没有人应该。所以不要给他们想法。