如何强制更新视图

时间:2014-03-17 06:45:59

标签: c# wpf mvvm view observablecollection

我的应用程序包含两个Views和一个ViewModel。 第一个View[AddView]用于创建对象,second[ShowView]用于显示对象。 ViewModel[DummyData]ObservableCollection和创建新对象所需的所有内容组成。

我的问题是: 当我从ShowView

添加对象时,如何强制更新AddView

这是DummyData

#region Fake Database
    private static ObservableCollection<Student> fakeStudentDataLayer;

    public UserDummyData()
    {
        fakeStudentDataLayer = new ObservableCollection<Student>()
        {
            new Student(){Name = "test1", Surname = "surnameTest1", Age = 22, Barcode = "testbarcode1", ClassLetter = 'A', ClassNumber = 6, ID = 1, ParentName = "parentTest1", ParentSurname = "ParentSurnameTitle1", Number = 22, DateOfCreation = new DateTime(2008, 12, 2), LastCheckIn = new DateTime(2014, 3, 9)},
            new Student(){Name = "test2", Surname = "surnameTest2", Age = 22, Barcode = "testbarcode2", ClassLetter = 'B', ClassNumber = 8, ID = 2, ParentName = "parentTest2", ParentSurname = "ParentSurnameTitle2", Number = 22, DateOfCreation = new DateTime(2008, 12, 2), LastCheckIn = new DateTime(2014, 3, 9)},
            new Student(){Name = "test3", Surname = "surnameTest3", Age = 22, Barcode = "testbarcode3", ClassLetter = 'C', ClassNumber = 10, ID = 3, ParentName = "parentTest3", ParentSurname = "ParentSurnameTitle3", Number = 22, DateOfCreation = new DateTime(2008, 12, 2), LastCheckIn = new DateTime(2014, 3, 9) }
        };
    }

    public ObservableCollection<Student> FakeStudentDataLayer
    {
        get { return fakeStudentDataLayer; }
        set { fakeStudentDataLayer = value; RaisePropertyChanged("FakeStudentDataLayer"); }
    }
    #endregion

    #region Commands
    private RelayCommand _addStudentCommand;
    public ICommand NewStudentCommand
    {
        get
        {
            return _addStudentCommand
                ?? (_addStudentCommand = new RelayCommand(() =>
                {
                    //Create new student
                    Student student = new Student();

                    //Set new student's properties
                    //TODO: Add ID value
                    student.Name = Name;
                    student.Surname = Surname;
                    student.ParentName = ParentName;
                    student.ParentSurname = ParentSurname;
                    student.ClassLetter = Convert.ToChar(ClassLetter.ToUpper());
                    student.ClassNumber = NumberConvertor(ClassNumber);
                    student.Class = Appender(ClassLetter, ClassNumber);
                    student.Number = Int32.Parse(Number);
                    student.Age = AgeConvertor(Age);
                    student.Barcode = Barcode;
                    student.ID = 6;
                    student.LastCheckIn = DateTime.Now;
                    student.DateOfCreation = DateTime.Now;

                    //TODO: ADD student to DATABASE
                    FakeStudentDataLayer.Add(student);
                }));
        }
    }
    #endregion

这是AddView

<Grid>
    <!--DataContext-->
    <Grid.DataContext>
        <dc:UserDummyData/>
    </Grid.DataContext>

    <!--Student TextBoxes-->
    <TextBlock x:Name="StudentNameWaterMark"
               Grid.Column="2"
               Text="{x:Static p:Resources.Name}"
               Style="{StaticResource WaterMarkStyle}"
               Visibility="{Binding
                    ElementName=StudentNameContentTextBox, 
                    Path=Text.IsEmpty, Converter={StaticResource 
                    WaterMarkRemover}}"/>
    <TextBox x:Name="StudentNameContentTextBox"
             Grid.Column="2"
             Text="{Binding Name}"
             Width="{Binding ElementName=StudentNameWaterMark,
                Path=Width}"
             Style="{StaticResource BasicTextBoxTextStyle}"
             Background="Transparent">
    </TextBox>
    <TextBlock Name="StudentSurnameWaterMark"
               Grid.Column="2" Grid.Row="1"
               Text="{x:Static p:Resources.Surname}"
               Style="{StaticResource WaterMarkStyle}"
               Visibility="{Binding
                    ElementName=StudentSurnameContentTextBox,
                    Path=Text.IsEmpty, Converter={StaticResource 
                    WaterMarkRemover}}"/>
    <TextBox x:Name="StudentSurnameContentTextBox"
             Grid.Column="2" Grid.Row="1"
             Text="{Binding Surname}"
             Width="{Binding ElementName=StudentSurnameWaterMark,
                Path=Width}"
             Style="{StaticResource BasicTextBoxTextStyle}"
             Background="Transparent">
    </TextBox>

    <!--Parent TextBoxes-->
    <TextBlock x:Name="ParentNameWaterMark"
               Grid.Column="2" Grid.Row="2"
               Text="{x:Static p:Resources.ParentName}"
               Style="{StaticResource WaterMarkStyle}"
               Visibility="{Binding 
                    ElementName=ParentNameContentTextBox, 
                    Path=Text.IsEmpty, Converter={StaticResource 
                    WaterMarkRemover}}"/>
    <TextBox x:Name="ParentNameContentTextBox"
             Grid.Column="2" Grid.Row="2"
             Text="{Binding ParentName}"
             Width="{Binding ElementName=ParentNameWaterMark,
                Path=Width}"
             Style="{StaticResource BasicTextBoxTextStyle}"
             Background="Transparent">
    </TextBox>
    <TextBlock x:Name="ParentSurnameWaterMark"
               Grid.Column="2" Grid.Row="3"
               Text="{x:Static p:Resources.ParentSurname}"
               Style="{StaticResource WaterMarkStyle}"
               Visibility="{Binding 
                      ElementName=ParentSurnameContentTextBox, 
                      Path=Text.IsEmpty, Converter={StaticResource 
                      WaterMarkRemover}}"/>
    <TextBox x:Name="ParentSurnameContentTextBox"
             Grid.Column="2" Grid.Row="3"
             Text="{Binding ParentSurname}"
             Width="{Binding ElementName=ParentSurnameWaterMark,
                Path=Width}"
             Style="{StaticResource BasicTextBoxTextStyle}"
             Background="Transparent">
    </TextBox>

    <!--Student Details TextBoxes-->
    <TextBlock x:Name="AgeWaterMark"           
               Grid.Column="5"
               Text="{x:Static p:Resources.Age}"
               Style="{StaticResource WaterMarkStyle}"
               Visibility="{Binding 
                      ElementName=AgeContentTextBox, 
                      Path=Text.IsEmpty, Converter={StaticResource 
                      WaterMarkRemover}}"/>
    <TextBox x:Name="AgeContentTextBox"
             Grid.Column="5"
             Text="{Binding Age}"
             Width="{Binding ElementName=AgeWaterMark,
                Path=Width}"
             Style="{StaticResource BasicTextBoxTextStyle}"
             Background="Transparent"/>

    <Grid Grid.Column="5" Grid.Row="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TextBlock x:Name="GradeNumberWaterMark"
                       Text="{x:Static p:Resources.GradeNumber}"
                       Style="{StaticResource GradeWaterMarkStyle}"
                       Visibility="{Binding 
                            ElementName=GradeNumberContentTextBox, 
                            Path=Text.IsEmpty, Converter={StaticResource 
                            WaterMarkRemover}}"/>
            <TextBox x:Name="GradeNumberContentTextBox"
                     Width="{Binding ElementName=GradeNumberWaterMark,
                        Path=Width}"
                     Text="{Binding ClassNumber}"
                     Style="{StaticResource TextBoxTextStyle}"
                     Background="Transparent"/>
        </Grid>
        <Grid Grid.Column="5">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TextBlock x:Name="GradeLetterWaterMark"
                       Text="{x:Static p:Resources.GradeLetter}"
                       Style="{StaticResource GradeWaterMarkStyle}"
                       Visibility="{Binding 
                            ElementName=GradeLetterContentTextBox, 
                            Path=Text.IsEmpty, Converter={StaticResource 
                            WaterMarkRemover}}"/>
            <TextBox x:Name="GradeLetterContentTextBox"
                     Width="{Binding ElementName=GradeLetterWaterMark,
                        Path=Width}"
                     Text="{Binding ClassLetter}"
                     Style="{StaticResource TextBoxTextStyle}"
                     Background="Transparent"/>
        </Grid>
    </Grid>

    <TextBlock x:Name="NumberWaterMark"
               Grid.Column="5" Grid.Row="2"
               Text="{x:Static p:Resources.NumberInClass}"
               Style="{StaticResource WaterMarkStyle}"
               Visibility="{Binding
                    ElementName=NumberContentTextBox, 
                    Path=Text.IsEmpty, Converter={StaticResource 
                    WaterMarkRemover}}"/>
    <TextBox x:Name="NumberContentTextBox"
             Grid.Column="5" Grid.Row="2"  
             Width="{Binding ElementName=NumberWaterMark,
                    Path=Width}"
             Text="{Binding Number}"
             Style="{StaticResource BasicTextBoxTextStyle}"
             Background="Transparent"/>

    <TextBlock x:Name="BarcodeWaterMark"
               Grid.Column="5" Grid.Row="3"
               Text="{x:Static p:Resources.Barcode}"
               Style="{StaticResource WaterMarkStyle}"
               Visibility="{Binding
                    ElementName=BarcodeContentTextBox, 
                    Path=Text.IsEmpty, Converter={StaticResource 
                    WaterMarkRemover}}"/>
    <TextBox x:Name="BarcodeContentTextBox"
             Grid.Column="5" Grid.Row="3"
             Width="{Binding ElementName=BarcodeWaterMark,
                    Path=Width}"
             Text="{Binding Barcode}"
             Style="{StaticResource BarcodeTextBoxTextStyle}"
             Background="Transparent"/>

    <!--Buttons-->
    <Grid Grid.Row="4" Grid.ColumnSpan="6">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Button Grid.Row="1"
                Content="{x:Static p:Resources.Add}"
                HorizontalAlignment="Left"
                Style="{StaticResource ButtonStyle}"
                Command="{Binding NewStudentCommand}"/>
        <Button Grid.Column="2"
                Content="{x:Static p:Resources.Clear}"
                HorizontalAlignment="Right"
                Style="{StaticResource ButtonStyle}"/>
    </Grid>
</Grid>

这是ShowView

<Grid>
    <!--DataContext-->
    <Grid.DataContext>
        <dc:UserDummyData/>
    </Grid.DataContext> 
    <!--DataGrid-->         
    <DataGrid AutoGenerateColumns="False"
          CanUserAddRows="True"
          CanUserDeleteRows="True"
          ItemsSource="{Binding FakeStudentDataLayer}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="{x:Static p:Resources.sName}"
                                Binding="{Binding Name}"/>
            <DataGridTextColumn Header="{x:Static p:Resources.sSurname}"
                                Binding="{Binding Surname}"/>
            <DataGridTextColumn Header="{x:Static p:Resources.sAge}"
                                Binding="{Binding Age}"/>
            <DataGridTextColumn Header="{x:Static p:Resources.sGrade}"
                                Binding="{Binding Class}"/>
            <DataGridTextColumn Header="{x:Static p:Resources.sNumber}"
                                Binding="{Binding Number}"/>
            <DataGridTextColumn Header="{x:Static p:Resources.LastCheckIn}"
                                Binding="{Binding LastCheckIn}"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

注意:如果我在AddView中放置ShowView中的代码,那么一切正常,但如果它们是这样的 - 两个单独的视图,则DataGrid不会更新。

编辑:我尝试使用相同的结构制作更简单的项目。令人难以置信的是,我没有做任何不同的事情。新采样器项目和这个项目之间的区别在于我使用了更基本的模型 - 只有两个属性。如果重要的话,我没有本地化。所以我的问题是为什么它适用于较小的项目而不是一个项目。

3 个答案:

答案 0 :(得分:1)

强制更新你的意思是什么?如果您的意思是添加数据,请尝试使用scaffolding

http://www.asp.net/visual-studio/overview/2013/aspnet-scaffolding-overview

答案 1 :(得分:0)

我不确定你的代码看起来如何,但我认为你有一个Window,包含多个视图,你的Window有一个MainViewModel例如,里面的视图有自己的viewmodel。 如果MainViewModel创建并处理其他视图,那么它获得了它们的实例,并且能够在那里调用方法。

所以也许你的问题是你想知道如何在视图模型之间进行通信?

这是我想到的一个小例子。 如果您有MainViewModel,DataAddViewModel和ShowViewModel。 MainViewModel创建DataAddViewModel和ShowViewModel。 DataAddViewModel有一个事件,在插入新数据时会触发该事件。 ShowViewModel具有与Listview或其他任何东西的绑定,以及触发该绑定的公共方法。

注意:以下只是一个例子。

DataAddViewModel 中的可能事件

public event EventHandler DataAddedEvent;

private void RaiseDataAddedEvent()
{
    var handler = this.DataAddedEvent;
    if (handler == null) return;
    handler(this, EventArgs.Empty);
}

MainViewModel 中可能的事件注册和处理

var _ShowVm = new ShowViewModel();
var _AddVm = new DataAddViewModel();
_addVm.DataAddedEvent += OnDataAdded;

//Notify our ShowViewModel about the new data
private void OnDataAdded(object sender, EventArgs e)
{
        _ShowVm.DataAdded();
}
ShowViewModel 中的公共方法

public void DataAdded(){
    RaisePropertyChanged("NameOfMyBinding");
}

答案 2 :(得分:0)

我最好的猜测是问题来自你使用两个独立的UserDummyData实例。在“显示”视图和“添加”视图中,您可以像这样设置DataContext

<Grid.DataContext>
    <dc:UserDummyData/>
</Grid.DataContext> 

这两行都构造了一个新的UserDummyData对象。因此,当您向其中一个添加数据时,数据不会添加到另一个中。你应该这样做:

<Grid ... DataContext="{x:Static p:Resources.MyUserDummyDataInstance}"/>

然后,当您将学生添加到UserDummyData时,两个视图都会显示新学生,因为他们的两个列表(实际上是相同的列表)都会有新学生。