【问题标题】:MVVM access Richtextbox flowdocument from VMMVVM 从 VM 访问 Richtextbox 流文档
【发布时间】:2017-09-29 22:27:51
【问题描述】:

我正在尝试制作一个带有 FlowDocument 的 RichTextBox,我可以在插入符号位置插入文本。我可以在文档末尾添加文本。我认为我在设置中遗漏了一些允许我的 VM 访问 Flowocument 的内容,或者我设置错误。如果我在我的 VM 中创建一个 FlowDocument 并尝试将我的 RichTextBox 设置为它,我会收到一个错误,即我的 MyEditor (RichTextBox) 不存在。我可以使用我从 ListBox 中调用的 AddItemBtn 将文本添加到 RichTextBox,所以至少有这么多的作品。

我的问题是“我应该如何设置我的 RichTextBox/FlowDocument?

XAML 代码

<Window x:Class="Scripter.Views.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Scripter.ViewModels"
    xmlns:wpftoolkit="clr-namespace:Xceed.Wpf.Toolkit;assembly=Xceed.Wpf.Toolkit"
    Title="MainWindow" Height="350" Width="725">


<Grid HorizontalAlignment="Stretch">

    <Grid HorizontalAlignment="Stretch" Height="72" Margin="10,14,0,0" VerticalAlignment="Top" Width="auto">
        <WrapPanel HorizontalAlignment="Left" Height="50" Margin="10,0,0,0" VerticalAlignment="Top">


        </WrapPanel>
        <Button x:Name="OpenFilesBtn" Content="Open" HorizontalAlignment="Left" Margin="15,10,0,0" VerticalAlignment="Top" Width="75" Command="{Binding OpenFileBtn}"/>
        <Button x:Name="SavefilesBtn" Content="Save" HorizontalAlignment="Left" Margin="104,10,0,0" VerticalAlignment="Top" Width="75" Command="{Binding SaveFileBtn}"/>
        <TextBlock x:Name="OpenFile" Text="{Binding OpenFile,Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="15,37,0,0" VerticalAlignment="Top" Width="353"/>
        <ComboBox x:Name="TipsBtn" SelectedIndex="0" ItemsSource="{Binding Path=Tabs, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding Path=SelectedOption}"  HorizontalAlignment="Left" Margin="538,10,0,0" VerticalAlignment="Top" Width="120"/>
        <Button x:Name="AddItemBtn" Content="Add Item" HorizontalAlignment="Left" Margin="417,10,0,0" VerticalAlignment="Top" Width="100" Command="{Binding AddItemBtn}" CommandParameter="{Binding ElementName=AddItemList,Path=SelectedItem}"/>

    </Grid>
    <Grid Margin="10,100,10,0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="2*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <RichTextBox  Grid.Column="0" x:Name="MyEditor" SelectionChanged="MyEditor_SelectionChanged" ScrollViewer.VerticalScrollBarVisibility="Auto" Margin="0" Height="Auto" HorizontalAlignment="Stretch"  VerticalAlignment="Stretch" Width="Auto" IsDocumentEnabled="True" AcceptsTab="True" AcceptsReturn="True" >
            <RichTextBox.Resources>
                <Style TargetType="{x:Type Paragraph}">
                    <Setter Property="Margin" Value="0" ></Setter>
                    <Setter Property="FontSize" Value="15"></Setter>
                </Style>
            </RichTextBox.Resources>
            <FlowDocument >
                <Paragraph >
                    <Run Text="{Binding TestText}" ></Run>
                </Paragraph>
            </FlowDocument>
        </RichTextBox>
        <ListBox x:Name="AddItemList" Grid.Column="1" Width="Auto" Height="Auto" ItemsSource="{Binding Path=OptionsToChoose}" SelectedItem="ItemSelected">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock x:Name="TextSelected" Text="{Binding Description}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

    </Grid>
</Grid>

有问题的虚拟机代码

public ScripterViewModel()
    {
        ScripterModel scripterModel = new ScripterModel();

        ObservableCollection<string> tabsChoice = new ObservableCollection<string>();
        tabsChoice.Add("Tabs");
        tabsChoice.Add("Buttons");
        Tabs = tabsChoice;

        this.OpenFileBtn = new DelegateCommand(chooseFile, canChooseFile).ObservesProperty(() => OpenFile);
        this.SaveFileBtn = new DelegateCommand(saveFile, canSaveFile).ObservesProperty(() => SaveFile);
        this.AddItemBtn = new DelegateCommand<Tabbed>(addItem);

        FlowDocument flowDoc = new FlowDocument();

        Paragraph p = new Paragraph(new Run("new paragraph"));
        flowDoc.Blocks.Add(new Paragraph(new Run("Paragraph 1")));
        flowDoc.Blocks.Add(p);

        //MyEditor = flowDoc;

    }

    public void MyEditor_SelectionChanged(object sender, RoutedEventArgs e)
    {
      // TextRange tempRange = new TextRange(MyEditor.Document.ContentStart, MyEditor.Selection.Start);
        MessageBox.Show("Selection Changed");

    }

    private string _testText;
    public string TestText
    {
        get
        {
            return _testText;
        }

        set
        {
            string _temp;
            _temp = _testText + value;
            SetProperty(ref _testText, value);
        }

    }

【问题讨论】:

    标签: c# mvvm richtextbox flowdocument


    【解决方案1】:

    嘿,我是 WPF 和 MVVM 的新手,但我会尽力帮助您。所以如果我错了不要怪我。

    1。设置Window.DataContext

    首先你必须告诉你的视图它可以从哪里得到数据。 这可以通过将此代码添加到您的 View.xaml 来完成:

    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    

    但请确保您的命名空间变量(此处为“本地”)指向您的 ViewModel。

    xmlns:local="clr-namespace:Client.ViewModel"
    

    这例如。指向我的 ViewModel 文件夹。

    2。定义一个 OnPropertyChanged 方法

    您的视图不会知道您是否修改了变量。因此,您需要一种方法来通知您的 View 有关更改。 首先将接口INotifyPropertyChanged 实现到您的ViewModel

    public class MainViewModel : ViewModelBase, INotifyPropertyChanged
    

    现在添加这段代码:

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName]string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    

    3。使用 OnPropertyChanged

    所以现在你有一个方法可以告诉你的视图一个变量已经改变了,但是你如何使用它呢? 为了向您解释这一点,我将使用您的 FlowDocument flowDoc

    让我们从定义您的FlowDocument 设置开始:

    private FlowDocument _flowDoc;
        
    

    现在让我们为 flowDoc 编写一个 getter 和 setter:

        public FlowDocument FlowDoc
        {
            get
            {
                return _flowDoc;
            }
            set
            {
               _flowDoc = value;
            }
        }
    

    现在是时候使用我们在 2 中创建的 OnPropertyChanged 方法了。 在 setter 部分,您要添加以下代码:

    OnPropertyChanged("variable");
    

    您的结果现在应该如下所示:

    public FlowDocument FlowDoc
        {
            get
            {
                return _flowDoc;
            }
            set
            {
               _flowDoc = value;
               OnPropertyChanged("FlowDoc");
            }
        }
    

    重要提示:记得将此应用于所有变量!

    4。正确使用 MVVM 模式

    MVVM 中,您有一个 Model 一个 View 和一个 ViewModel。 模型用于您的数据,因此如果可能,请不要将数据存储在您的 ViewModel 中,而是使用数据类作为 ex。

    您可以查看 this 和/或 this


    正如我在开头所说的那样,我对这一切都很陌生,但我希望它会有所帮助 你。随时问。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多