在我的应用程序中,我需要一个系统,其中一些消息显示给用户有一个"不要再次显示"复选框。在"设置"菜单中,我想要有一个"驳回消息"部分;每个消息的名称和复选框,因此用户可以在需要时取消它们。如果消息被驳回,用户在消息对话框中选择的最后一个选项应该成为默认选项。
另外,设置应该保存到XML文件中——包括消息抑制状态和默认选择。我目前的解决方案非常粗糙,我想知道是否有更好的方法。
消息类定义为:
Public Class Message
Public Property title As String
Public Property content As String
Public Property buttons As Utilities.Enums.messageButtonTypes 'Ok/Cancel, Yes/No, etc.
Public Property allowDoNotShowAgain As Boolean = False 'whether the message is dismissable
Public Property doNotShowAgain As Boolean = False 'the actual dismiss state
Public Property result As Boolean
Public Property rememberedResult As Boolean 'last user choice if the message is dismissed
End Class
特定消息在MSG模块中初始化:
Module Msg
'This message is not dismissable
Public connectionNotEstablished As New Message() With {
.title = "Connection not established",
.content = "Connection not established. Please check if the host application is running.",
.buttons = Utilities.Enums.messageButtonTypes.Ok
}
'This message is dismissable
Public noResultsPlotsDefined As New Message() With {
.title = "No plots defined",
.content = "You have not defined any plots. Would you like to run the study anyway?",
.buttons = Utilities.Enums.messageButtonTypes.YesNo,
.allowDoNotShowAgain = True
}
'Just a list to store references to all the messages for binding, looping, etc.
Public allMessages As New List(Of Message) From {
connectionNotEstablished,
noResultsPlotsDefined
}
Public Function ShowMessage(message As Message) As Boolean
If message.doNotShowAgain Then message.result = message.rememberedResult : Return message.rememberedResult 'If message is dismissed, return the last user choice
Dim messageDialog As New MessageDialog(message.title, message.content, message.buttons, message.allowDoNotShowAgain, message.defaultButtonCustomCaption, message.cancelButtonCustomCaption)
message.result = messageDialog.ShowDialog()
message.doNotShowAgain = messageDialog.doNotShowAgain
If message.doNotShowAgain Then message.rememberedResult = message.result
Return message.result
End Function
End Module
在各种函数中调用特定的消息,例如:
Msg.ShowMessage(connectioNotEstablished)
到目前为止,非常简单——在构建应用程序时非常方便地使用。我不确定的是AppSettings类。如前所述,我需要存储每条消息的一些属性,以便我可以wpf绑定到设置窗口中的消息列表。现在,AppSettings有一个对MSG类消息列表的引用:
Public Class AppSettings
Public Property messages As List(Of Message) = Msg.allMessages
Public Sub SaveToDefaultPath()
Save(Constants.Paths.settingsFilePath)
End Sub
Private Sub Save(ByVal filename As String)
Using sw As StreamWriter = New StreamWriter(filename)
Dim xmls As XmlSerializer = New XmlSerializer(GetType(AppSettings))
xmls.Serialize(sw, Me)
End Using
End Sub
Private Function Read(ByVal filename As String) As AppSettings
Using sw As StreamReader = New StreamReader(filename)
Dim xmls As XmlSerializer = New XmlSerializer(GetType(AppSettings))
Return TryCast(xmls.Deserialize(sw), AppSettings)
End Using
End Function
End Class
在我的设置WPF窗口中,我可以绑定到messages
属性,并选择显示title
为TextBlock,doNotShowAgain
为CheckBox,rememberedResult
为ComboBox。我还没有这么做,但我认为在当前的应用程序架构下应该是相当直接的。
问题在于XML的序列化和反序列化(参见AppSettings
类的最后两个函数)。因为这个类存储了对整个消息列表的引用,其中不仅有title
、doNotShowAgain
和rememberedResult
,还有消息内容及其其他属性,这些属性确实使XML文件变得混乱。
我不知道如何解决这个问题。也许,我可以在AppSettings
中只存储每条消息所需的变量,但这需要某种双向转换器或其他东西。到这里,我开始怀疑这是否真的是实现我所需要的正确方法。
我不可能是第一个实现这个的人,所以也许有这样一个约定。有什么建议吗?
编辑:在等待答案的同时,我已经成功地实现了将消息解散状态保存为XML -不幸的是,它保存了整个message
类数据,而不仅仅是title
,doNotShowAgain
和rememberedResult
。为了使它工作,我只需要做一个小的更改—将AppSettings
中的属性messages
声明为Array而不是List,这样XML反序列化器就不会将消息附加到该List中,而只是将其作为一个整体替换。
Public Class AppSettings
Public Property Messages() As Message() = Msg.allMessages.ToArray()
...
End Class
因此,虽然这可以工作(将这些messages
绑定到WPF窗口也可以工作),但XML文件中充斥着每个消息的不必要值,例如:
<Message>
<title>No plots defined</title>
<content>You have not defined any plots. Would you like to run the study anyway?</content>
<buttons>YesNo</buttons>
<allowDoNotShowAgain>true</allowDoNotShowAgain>
<doNotShowAgain>false</doNotShowAgain>
<result>false</result>
<rememberedResult>false</rememberedResult>
</Message>
但是对于这个用例,对于XML文件中的每条消息只使用这个位就足够了:
<Message>
<title>No plots defined</title>
<doNotShowAgain>false</doNotShowAgain>
<rememberedResult>false</rememberedResult>
</Message>
所以我的问题仍然是——这里最好的解决方案是什么?我猜对了吗?
看来您唯一的问题是Xml文件中有混乱。所以你可以用<XmlIgnore>
Public Class Message
Public Property title As String
<XmlIgnore>
Public Property content As String
<XmlIgnore>
Public Property buttons As Utilities.Enums.messageButtonTypes 'Ok/Cancel, Yes/No, etc.
<XmlIgnore>
Public Property allowDoNotShowAgain As Boolean = False 'whether the message is dismissable
Public Property doNotShowAgain As Boolean = False 'the actual dismiss state
<XmlIgnore>
Public Property result As Boolean
Public Property rememberedResult As Boolean 'last user choice if the message is dismissed
End Class
序列化器既不序列化也不反序列化这些属性。
现在您还可以序列化由linq查询定义的消息子集,如下所示
<XmlIgnore>
Public Property messages As List(Of Message) = Msg.allMessages
<XmlElement("messages")>
Public Property messagesAllowDoNotShowAgain As List(Of Message) = Msg.allMessages.Where(Function(m) m.allowDoNotShowAgain).ToList()