首页 > 解决方案 > 了解将数据从页面传递到用户控件

问题描述

我一直在努力解决如何在页面和 UserControl 之间传递数据,并且可以使用一些说明来说明我可能做错了什么。如果我删除代码的数据部分并仅用 TextBlocks 替换它,我知道 UserControl 正在工作。

我确实知道 NetWorth 正在显示,但只是看不出为什么List<Account>没有传递。我不知道我在这里做错了什么。

PanelNavigation.xaml

        <!-- Navigation Section -->
        <ScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto" CanContentScroll="True" Grid.Row="1" Margin="0,0.333,0,0" Grid.ColumnSpan="2">
            <UserControls:NavigationPanel DataContext="{Binding Accounts}"/>
        </ScrollViewer>

        <!-- Networth Panel -->
        <Grid Grid.Row="2" Height="40">
            <Border BorderThickness="0,1,0,0" BorderBrush="{StaticResource MenuBarBrush}" Background="{StaticResource BackgroundLightBrush}">
                <Grid Margin="5,5,10,5">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>

                    <TextBlock Margin="10,1,10,1" FontSize="16" FontWeight="Normal" Grid.Column="0" Foreground="#FF346C9C" Text="Net Worth" />
                    <TextBlock FontSize="16" FontWeight="Normal" Grid.Column="1"
                               HorizontalAlignment="Right" Text="{Binding NetWorth, Converter={StaticResource CurrencyConverter}}"
                               Foreground="{Binding NetWorth, Converter={StaticResource ChangeColor}}"/>
                </Grid>
            </Border>
        </Grid>

PanelNavigation.xaml.cs


using APTest.ViewModels;
using System.Windows.Controls;

namespace APTest.Views
{
    /// <summary>
    /// Interaction logic for PanelNavigation.xaml
    /// </summary>
    public partial class PanelNavigation : Page
    {
        public PanelNavigation()
        {
            InitializeComponent();

            this.DataContext = new VMNavigationPanel(this);

        }
    }
}

导航面板.xaml

<UserControl x:Class="APTest.UserControls.NavigationPanel"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:UserControls="clr-namespace:APTest.UserControls"
             mc:Ignorable="d" 
             d:DesignHeight="800" d:DesignWidth="400">

    <StackPanel>
        <StackPanel>
            <ItemsControl x:Name="DataTest" ItemsSource ="{Binding Accounts}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding TotalBalance}" />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </StackPanel>
    </StackPanel>

</UserControl>
    

导航面板.xaml.cs

using System.Windows.Controls;

namespace APTest.UserControls
{
    public partial class NavigationPanel : UserControl
    {
        public NavigationPanel()
        {
            InitializeComponent();
        }
    }

最后

VMNavigationPanel.cs

using AccountingPlus.ViewModels;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace APTest.ViewModels
{
    class VMNavigationPanel  : BaseViewModel
    {
        private Page mPage;
        private ObservableCollection<Account> accounts;
        public ObservableCollection<Account> Accounts {
            get => accounts;
            set {
                accounts = value;
                OnPropertyChanged();
            }
        }

        public double NetWorth { get; set; } = 127492.30;

        public VMNavigationPanel(Page page)
        {
            mPage = page;

            Accounts = new ObservableCollection<Account>();

            Account test = new Account();
            test.TotalBalance = 100234.23;

            Accounts.Add(test);
        }
    }

    public class Account
    {
        public double TotalBalance {get; set;}
    }
}

BaseViewModel.cs

using PropertyChanged;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace APTest
{
    [AddINotifyPropertyChangedInterface]
    class BaseViewModel : INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged = (Sender, e) => { };

        protected void OnPropertyChanged([CallerMemberName] string name = null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }
}

标签: c#wpfxamluser-controls

解决方案


首先,您需要模型中的属性来绑定对象。您不能绑定字段。

这样您的 Account 类应该是这样的:

public class Account
{
    public double TotalBalance { get; set; }

}

还要记住这一点,要在 WPF 中更新 UI,我们需要使用 ObservableCollections。例如,如果您单击一个按钮并将一个项目添加到您的 Accounts 集合中,则该项目将在您的集合中,但在 UI 中,如果您使用 List 集合,您将看不到更新的结果,这就是您需要使用 ObservableCollections 的原因。 https://docs.microsoft.com/en-us/dotnet/api/system.collections.objectmodel.observablecollection-1?view=netcore-3.1

另一件事是您的绑定拼写错误。在您的 NavigationPanel.xaml 中,它应该是 TotalBalance。

<TextBlock Text="{Binding TotalBalnce}" />

这是您的视图模型的工作代码:

我还为您实现了 INotifyPropertyChanged 接口,但没有与任何其他属性一起使用。

class VMNavigationPanel : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged<T>(ref T property, T value, [CallerMemberName] string propertyName = null)
    {
        property = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private Page mPage;

    public double NetWorth { get; set; } = 127492.30;

    private ObservableCollection<Account> accounts;
    public ObservableCollection<Account> Accounts
    {
        get => accounts;
        set
        {
            accounts = value;
        }
    }

    public VMNavigationPanel(Page page)
    {
        mPage = page;

        Accounts = new ObservableCollection<Account>();

        Account test = new Account();
        test.TotalBalance = 100234.23;

        Accounts.Add(test);
    }

}

public class Account
{
    public double TotalBalance { get; set; }

}

推荐阅读