使用MVVM时,XamlWriter可以读取文本框内容吗?

时间:2014-01-09 13:46:36

标签: c# wpf xaml mvvm

我一直在寻找这个。正如标题所说,XamlWriter有没有办法阅读文本框的内容,以及文本框本身的定义?

文本框未直接输入Xaml,因为它们已在运行时绑定到MVVM模式。目前,XamlWriter只是保存文本框而不包含其内容。

保存视图的示例代码,但没有文本框内容:

string mystrXAML = XamlWriter.Save(StackPanelContent);

        string name = txtname.Text;

        FileStream fs = File.Create(String.Format(@"C:\Desktop\" + name + ".txt"));
        StreamWriter sw = new StreamWriter(fs);
        sw.Write(mystrXAML);
        sw.Close();
        fs.Close();

编辑:

花了很多时间思考和研究如何做到这一点仍然无法找到正确的答案。这是我的XAML代码,它仍然没有保存文本框内容,这是因为它们是绑定的(我正在研究)

XAML:

<ListView ItemsSource="{Binding Title}" ItemTemplate="{DynamicResource Template}">
     <ListView.ItemContainerStyle>
            <Style>
                <Setter Property="FrameworkElement.Margin" Value="20,20,0,0"/>
            </Style>
     </ListView.ItemContainerStyle>
            <ListView.Resources>
                <DataTemplate x:Key="Template">
                   <TextBox Text="{Binding .}" Width="200" HorizontalAlignment="Left" />
                </DataTemplate>
            </ListView.Resources>
</ListView>

<ListView x:Name="QuestionList" ItemsSource="{Binding Question}" ItemTemplate  {DynamicResource Template}">
      <ListView.ItemContainerStyle>
            <Style>
                <Setter Property="FrameworkElement.Margin" Value="40,20,0,0"/>
            </Style>
      </ListView.ItemContainerStyle>
            <ListView.Resources>
                <DataTemplate x:Key="Template">
                    <TextBox Text="{Binding .}" Width="200" HorizontalAlignment="Left"/>
                </DataTemplate>
            </ListView.Resources>
</ListView>

1 个答案:

答案 0 :(得分:3)

我只是不了解你...你来到这个网站并寻求有用的建议,当你得到有用的建议时,你会忽略它并一次又一次地问你的(几乎相同的)问题。您已经被几个不同的用户告知,在WPF中,我们使用数据,而不是 UI控件。因此,不应将TextBox es保存为对您毫无意义的所有额外属性,而应将刚才文本保存在绑定到TextBox es的集合数据中。

现在我希望你不要再次接受这个,但在某些时候,你必须开始倾听那些知道他们正在谈论的人。但是,如果你的心脏是以你自己的顽固方式,而不是正确的方式,那么我可以提请你注意MSDN上的XamlWriter Class页面:

  

此方法启用的序列化具有一系列限制。这是因为启用的序列化是显式运行时,并且无法访问原始XAML中的可能设计时信息(如果有)。有关详细信息,请参阅Serialization Limitations of XamlWriter.Save

从MSDN上的链接页面:

  

序列化过程将取消引用各种标记扩展格式(如StaticResource或Binding)对对象的公共引用。在应用程序运行时创建内存中对象时,这些已被解除引用,并且Save逻辑不会重新访问原始XAML以恢复对序列化输出的此类引用。 这可能会将任何数据绑定或资源获取的值冻结为运行时表示最后使用的值,只有有限或间接的能力将此值与本地设置的任何其他值区分开来。

我已经突出显示了一个部分,它基本上表示是,您可以使用XamlWriter.Save方法保存控件的属性值。但是,我无法告诉你为什么你的价值观没有被保存。

现在当你说你到处搜索时,你似乎错过了最明显的问题搜索术语:XamlWriter Class。为了将来参考,如果您使用这些单词进行搜索,那么您已经在最佳结果中找到了所有这些内容。

但是,保存数据而不是UI控件更有意义。考虑一下......你已经有了从你的收藏中生成/显示这些TextBox es的机制,那么为什么你不能使用它?将数据保存在数据库或文本文件中,并在重新加载时,使用现有代码从集合中重新填充TextBox es。它实际上就像使用加载的数据在视图模型中填充集合一样简单。您甚至可以使用与您已经使用的代码相同的代码保存数据集,或者甚至更少。

这就是如何正确完成的。现在,您可以接受并以正确的方式继续您的项目,或者您可以继续忽略此建议并提出更多几乎相同的问题。现在,我认为这至少是你的第三个问题,询问如何将XAML存储在文件或数据库中。如果你刚刚接受了之前给你的好建议,或者甚至做了正确的搜索,你本可以节省包括你自己在内的所有人。

除了其他任何东西之外,它更容易持久化数据而不是UI控件。

最后,您是否注意到您的(非常相似)问题直到现在才得到解答?你有没有看到大多数问题通常在这里得到解答?我不是唯一一个注意到所有类似问题的人,这表明当用户滥用本网站时,StackOverflow社区整体上不喜欢它,期望他人为他们完成所有工作。< / p>

现在你可能不会相信这一点,因为我们已经发生了冲突&#39;以前,但所有这些建议都是为了帮助你。抱歉,如果我的任何评论冒犯了您,但如果您根据the rules使用此网站,那么您将从中获得更多。例如,不要一次又一次地问同一个问题,只需编辑原始问题if you didn't get a satisfactory answer即可。编辑后的问题会再次回到未答复队列的顶部,以吸引更多关注。

我希望你这次接受我的建议并祝你好运。


更新&gt;&gt;&gt;

来自MSDN的链接页面告诉我们XamlWriter 可以保存数据绑定数据,但不幸的是,我无法告诉你为什么你的工作不起作用。

说实话,保存string是不够的。您需要保存所有相关数据。显示,编辑保存此数据的最简单方法是创建实现INotifyPropertyChanged接口的自定义类。例如,对于您的场景,我将创建一个Question类,如下所示:

[Serializable]
public class Question // Implement INotifyPropertyChanged correctly here
{
    public string Title { get; set; }
    public string Text { get; set; }
    public string Answer { get; set; }
}

如果您的问题是多种选择,那么您可以这样做:

[Serializable]
public class Question // Implement INotifyPropertyChanged correctly here
{
    public string Title { get; set; }
    public string Text { get; set; }
    public List<Answer> Answers { get; set; }
    public Answer CorrectAnswer { get; set; }
}

当然,你应该有private个字段支持这些公共属性......这只是一个简化的例子。请注意使用SerializableAttribute ...这样您只需几行代码即可保存数据。

您可以根据需要构建属性,但您的想法是将所有相关数据封装到一个类中。然后,您可以为该类类型提供DataTemplate,让我们将其称为Template,并定义一组控件,以显示相关的属性值。

现在,好的部分......你可以在视图模型中创建该类型的集合......:

public ObservableCollection<Question> Questions { get; set; }

...并将任何集合控件的ItemTemplate属性设置为DataTemplate

<ListBox ItemsSource="{Binding Questions}" ItemTemplate="{StaticResource Template}" />

然后集合中的每个Question项都将完全按照您在DataTemplate中的定义进行渲染。因此,要回答有关如何重新加载数据的问题,只需在视图模型中重新填充Questions集合,WPF模板系统将以与其完全相同的方式正确地为我们重新填充UI。之前就已经保存了数据。

现在你可以看到......我花了很多时间向你解释这一切。我相信您可以使用新发现的搜索技能回答您可能遇到的任何其他问题。

首先,这里有一些有用的文章:

Serialization (C# and Visual Basic)
Walkthrough: Persisting an Object (C# and Visual Basic)
Data Templating Overview
INotifyPropertyChanged Interface