繁体   English   中英

更改数据后视图的值不更新

[英]Values of View don't update after changing data

我正在尝试构建一个应用程序,从 api 收集水坝和天气预报信息并将数据显示给用户。

如下所示,主页应该与大坝信息和天气预报信息相似。 蓝图

所以,我想为卡片制作一个组件,我可以将它重用于数据。 换句话说,我想把 1) mainCards 放到 2)mainPage 中,这样我就可以拥有一个充满卡片的页面。 然后,我想将 mainPage 放在 3)mainWindow 之上。

当我单击左侧显示“大坝信息”和“天气信息”的菜单按钮时,我想更改紫色卡片内的值。 当我按下“大坝信息”按钮时,我希望紫色卡片从 API 获取大坝数据并将其显示在屏幕上。 与“天气信息”按钮相同。

问题是,当我运行代码并在控制台上显示它们时,我可以清楚地看到绑定到卡片中文本块的值发生了变化。 但是,实际的 UI 不会更新更改。 INotifyProperty 表示当我按下按钮时,我为当前视图实现的视图模型会发生变化。 它还说,当我按下按钮时,紫色卡片组件的视图模型中的值(我绑定到紫色卡片的文本块)会发生变化。

我实现了一个基类,它为所有视图模型实现了 INotifyPropertyChanged,并为所有命令实现了 RelayCommand。

我假设使用 INotifyPropertyChanged,视图会自动更改 UI 值,但事实并非如此。 我已经尝试将绑定模式设置为 Two Way ,但它不起作用。 我尝试在主页(包含大量紫色卡片组件的页面)的视图模型中设置某些值,然后使紫色卡片视图模型获取并反映它。 但它不起作用。

请帮我。 我已经处理这个问题一个星期了。 我没有太多时间来努力改变视图及其组成部分。 我是 MVVM 模式和 WPF 的新手,完全迷路了。

主窗口的 xml 如下所示

<Grid>
    <RadioButton Content="Dam Info"
            Command="{Binding ChangeMainPageForDamCommand}"
            CommandParameter="Dam"/>
    <RadioButton Content="Weather Info"
            Command="{Binding ChangeMainPageForWeatherCommand}"
            CommandParameter="Weather"/>
    <RadioButton Content="My data"
            Command="{Binding DetailPageCommand}"/>

    <ContentControl Content="{Binding CurrentView,
            Mode=TwoWay,
            UpdateSourceTrigger=PropertyChanged}"/>
</Grid>

主窗口的视图模型如下所示

private object _currentView;
    public object CurrentView
    {
        get { return _currentView; }
        set
        {
            _currentView = value;
            OnPropertyChanged();
        }
    }


    public RelayCommand MainPageCommand { get; set; }
    public RelayCommand DetailPageCommand { get; set; }

    public RelayCommand ChangeMainPageForDamCommand { get; set; }

    public RelayCommand ChangeMainPageForWeatherCommand { get; set; }


    public MainPageViewModel DamMainPageVM { get; set; }


    public MainPageViewModel WeatherMainPageVM { get; set; }


    public MainPageViewModel MainPageVM { get; set; }
    public DetailPageViewModel DetailPageVM { get; set; }


    public MainWindowViewModel()
    {
        MainPageVM = new MainPageViewModel("Dam");

        CurrentView = MainPageVM;

        DetailPageVM = new DetailPageViewModel();

        ChangeMainPageForDamCommand = new RelayCommand(o =>
        {
            CurrentView = null;
            DamMainPageVM = new MainPageViewModel("Dam");
            CurrentView = DamMainPageVM;
            Debug.WriteLine("ChangeMainPageFor  Dam  Command executed");
        });

        ChangeMainPageForWeatherCommand = new RelayCommand(o =>
        {
            WeatherMainPageVM = new MainPageViewModel("Weather");
            CurrentView = WeatherMainPageVM;
            Debug.WriteLine("ChangeMainPageFor  Weather  Command executed");
        });

        DetailPageCommand = new RelayCommand(o =>
        {
            CurrentView = DetailPageVM;
        });
    }

包含卡片的 mainPage 的 xml 如下所示

<Grid>
    <components:MainCard/>
    <components:MainCard/>
    <components:MainCard/>
    <components:MainCard/>
    <components:MainCard/>
    <components:MainCard/>
</Grid>

主页的视图模型如下所示

public MainCardDatum MainCardDatumItem = new MainCardDatum();

    public RelayCommand GetDamDetailCommand { get; set; }

    private MainCardViewModel _mainCardViewModel;
    public MainCardViewModel MainCardViewModel
    {
        get
        {
            return _mainCardViewModel;
        }
        set
        {
            _mainCardViewModel = value;
            OnPropertyChanged(nameof(MainCardViewModel));
        }
    }

    public MainPageViewModel() { }
    public MainPageViewModel(string pageName)
    {
        var d = new MainCardViewModel(pageName);
        GetMainPage(pageName);
        Debug.WriteLine(pageName+" is ON");
    }
    
    public void GetMainPage(string pageName)
    {
        GenerateMainCard(pageName);

        Debug.WriteLine(pageName+" made the page.");
    }
    
    private void GenerateMainCard(string pageName)
    {
        if (pageName == "Dam")
        {
            MainCardDatumItem.Id = 1;
            MainCardDatumItem.MainCardName = "damDummyInfoName";
            MainCardDatumItem.MainCardOption = "damDummyInfoOption";
        }
        else if (pageName == "Weather")
        {
            MainCardDatumItem.Id = 1;
            MainCardDatumItem.MainCardName = "weatherDummyInfoName";
            MainCardDatumItem.MainCardOption = "weatherDummyInfoOption";
        }
        else
        {
            Debug.Write("What?");
        }
    }

主卡(紫卡组件)xaml 如下

<Grid>
    <StackPanel>
        <TextBlock Name="nameHehe" 
               Text="{Binding MainCardName,
                        Mode=TwoWay,
                        UpdateSourceTrigger=PropertyChanged}"/>

        <TextBlock Name="optionHehe"
                Text="{Binding MainCardOption}"/>
    </StackPanel>

    <Button Background="Transparent"
            Command="{Binding GetDamDetailCommand}"/>
</Grid>

最后,主卡(紫色卡组件)的视图模型如下

public MainPageViewModel MainPageVM = new MainPageViewModel();

    private string _mainCardName;
    public string MainCardName
    {
        get
        {
            return _mainCardName;
        }
        set
        {
            _mainCardName = value;
            OnPropertyChanged(nameof(MainCardName));
        }
    }

    private string _mainCardOption;
    public string MainCardOption
    {
        get
        {
            return _mainCardOption;
        }
        set
        {
            _mainCardOption = value;
            OnPropertyChanged(nameof(MainCardOption));
        }
    }

    public RelayCommand ClickCommand { get; set; }
    public RelayCommand GetDamDetailCommand { get; set; }
    public RelayCommand GetWeatherDetailCommand { get; set; }

    public MainCardViewModel()
    {
        GenerateCardsForDam();

        GetDamDetailCommand = new RelayCommand(o =>
        {
            MainCardName = "changed1";
            MainCardOption = "changed2";
        });
    }
    public MainCardViewModel(string pageName)
    {
        if (pageName == "Dam")
            GenerateCardsForDam();
        else
            GenerateCardsForWeather();

        GetDamDetailCommand = new RelayCommand(o =>
        {
            GenerateCardsForWeather();
        });
    }

    public void GenerateCardsForDam()
    {
        MainCardName = "DamName1";
        MainCardOption = "DamOption1";
        Debug.WriteLine("GenerateCardsForDam executed");
    }
    public void GenerateCardsForWeather()
    {
        MainCardName = "WeatherName1";
        MainCardOption = "WeatherOption1";
        Debug.WriteLine("GenerateCardsForWeather executed");
    }

我在 xaml 中删除了所有与此问题无关的不必要代码。

我究竟做错了什么? 请帮忙。

另外,很高兴知道我可以提出和回答与编程相关的问题的任何不和谐服务器。 我很难在文本中解释这个问题。 如果你知道,请告诉我。

非常感谢您到目前为止的阅读。 抱歉解释混乱。

https://github.com/yk170901/dnw.git上面是我的项目的Github存储库。 我尝试正确添加它,但是当我尝试上传它时,项目文件夹以某种方式变为空。 所以我添加了一个 zip,希望你能看到 zip 文件的问题。 带来不便敬请谅解。

您在 App.xaml 中为 MainPage(一个用户控件)定义了一个 DataTemplate。

<DataTemplate DataType="{x:Type viewModel:MainPageViewModel}">
    <view:MainPage/>
</DataTemplate>

应用此 DataTemplate 时,应实例化 MainPage 并将 MainPageViewModel 的实例设置为 MainPage 的 DataContext。

但是,您在 MainPage.xaml 中添加了如下所示的代码块。

<UserControl.DataContext>
    <viewModels:MainPageViewModel/>
</UserControl.DataContext>

这意味着当 MainPage 被实例化时,MainPageViewModel 的一个实例也将被实例化,并且该实例将被设置为 MainPage 的 DataContext。 这似乎阻止了 DataTemplate 按预期工作。

因此,解决方案是在 MainPage.xaml 中删除该代码块。

此外,我发现无论 MainPageViewModel 实例如何,MainPage 的外观都是相同的,因此您将无法从外观上检查差异。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM