【问题标题】:Public variable doesn't show up in class members list公共变量未显示在类成员列表中
【发布时间】:2020-01-21 10:04:39
【问题描述】:

我对这门语言完全陌生,所以我觉得这是一个有点傻的问题..

我正在尝试通过来自his example repository 的示例使用 MahApps.Metro 框架创建一个汉堡菜单,该示例是带有 MVVM 的 V4 版本。

复制他示例的所有结构,它可以正常工作,但现在我不知道如何继续。我不知道如何从 SearchViewModel 中获取 MainViewModel 的属性,因为在访问对象时我看不到它的属性。

另外,我不知道如何绑定这些属性或如何将 SearchView.xaml 中的按钮与使用 MainViewModel 属性的操作链接。

这些都是我相关的类,不过你可以按照his example repo的例子来学习

MainWindow.xaml

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

<Grid.Resources>
    <core:SelectedItemToContentConverter x:Key="SelectedItemToContentConverter" />

    <!--  this is the template for the items (options too)  -->
    <DataTemplate x:Key="MenuItemTemplate" DataType="{x:Type Controls:HamburgerMenuIconItem}">
        <Grid x:Name="RootGrid" Height="48" Background="Transparent">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="48" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <ContentControl Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{Binding Icon}" Focusable="False" />
            <TextBlock Grid.Column="1" VerticalAlignment="Center" FontSize="16" Text="{Binding Label}" />
        </Grid>
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Controls:HamburgerMenu}}, Path=IsPaneOpen}" Value="False">
                <Setter TargetName="RootGrid" Property="ToolTip" Value="{Binding ToolTip, Mode=OneWay}" />
            </DataTrigger>
        </DataTemplate.Triggers>
    </DataTemplate>

    <!--  these are the templates for the view models  -->
    <DataTemplate DataType="{x:Type viewModels:HomeViewModel}">
        <views:HomeView DataContext="{Binding}" />
    </DataTemplate>
    <DataTemplate DataType="{x:Type viewModels:PrivateViewModel}">
        <views:PrivateView DataContext="{Binding}" />
    </DataTemplate>
    <DataTemplate DataType="{x:Type viewModels:SettingsViewModel}">
        <views:SettingsView DataContext="{Binding}" />
    </DataTemplate>
    <DataTemplate DataType="{x:Type viewModels:AboutViewModel}">
        <views:AboutView DataContext="{Binding}" />
    </DataTemplate>

    <Controls:HamburgerMenu Grid.Row="1" x:Name="HamburgerMenuControl" HamburgerVisibility="Hidden" HamburgerWidth="48" ItemTemplate="{StaticResource MenuItemTemplate}" ItemsSource="{Binding MenuItems}" IsPaneOpen="True" SelectedIndex="0" Style="{StaticResource HamburgerMenuCreatorsStyle}" OpenPaneLength="350" VerticalScrollBarOnLeftSide="False" Grid.RowSpan="3" Grid.ColumnSpan="2">
        <!--  select the tag (ViewModel) of the selected item (options item)  -->
        <Controls:HamburgerMenu.Content>
            <MultiBinding Converter="{StaticResource SelectedItemToContentConverter}">
                <Binding FallbackValue="{x:Null}" Mode="OneWay" Path="SelectedItem.Tag" RelativeSource="{RelativeSource Self}" />
                <Binding FallbackValue="{x:Null}" Mode="OneWay" Path="SelectedOptionsItem.Tag" RelativeSource="{RelativeSource Self}" />
            </MultiBinding>
        </Controls:HamburgerMenu.Content>
    </Controls:HamburgerMenu>

</Grid.Resources>

PropertyChangedViewModel 基础模型

using System.ComponentModel;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;

namespace ExampleProject.ViewModels
{
    public class PropertyChangedViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

MainViewModel

namespace ExampleProject.ViewModels
{
    public class MainViewModel : PropertyChangedViewModel
    {
        private HamburgerMenuItemCollection _menuItems;
        private HamburgerMenuItemCollection _menuOptionItems;

        public MainViewModel()
        {
            this.CreateMenuItems();
        }

        public void CreateMenuItems()
        {
            MenuItems = new HamburgerMenuItemCollection
            {
                new HamburgerMenuIconItem()
                {
                    Icon = new PackIconMaterial() {Kind = PackIconMaterialKind.Magnify},
                    Label = "Search Item",
                    ToolTip = "The Search view.",
                    Tag = new SearchViewModel(this)
                },
                new HamburgerMenuIconItem()
                {
                    Icon = new PackIconMaterial() {Kind = PackIconMaterialKind.CreditCardOutline},
                    Label = "Payment item",
                    ToolTip = "Payment.",
                    Tag = new PaymentViewModel(this)
                },
                new HamburgerMenuIconItem()
                {
                    Icon = new PackIconMaterial() {Kind = PackIconMaterialKind.BookmarkMultipleOutline},
                    Label = "The Bookmarks",
                    ToolTip = "The bookmarks item.",
                    Tag = new BookmarksViewModel(this)
                }
            };

            MenuOptionItems = new HamburgerMenuItemCollection
            {
                new HamburgerMenuIconItem()
                {
                    Icon = new PackIconMaterial() {Kind = PackIconMaterialKind.Help},
                    Label = "About",
                    ToolTip = "Some help.",
                    Tag = new AboutViewModel(this)
                }
            };
        }

        public HamburgerMenuItemCollection MenuItems
        {
            get { return _menuItems; }
            set
            {
                if (Equals(value, _menuItems)) return;
                _menuItems = value;
                OnPropertyChanged();
            }
        }

        public HamburgerMenuItemCollection MenuOptionItems
        {
            get { return _menuOptionItems; }
            set
            {
                if (Equals(value, _menuOptionItems)) return;
                _menuOptionItems = value;
                OnPropertyChanged();
            }
        }
    }
}

SearchViewModel

namespace ExampleProject.ViewModels
{
    public class SearchViewModel : PropertyChangedViewModel
    {
        private readonly PropertyChangedViewModel _mainViewModel;

        public SearchViewModel(PropertyChangedViewModel mainViewModel)
        {
            _mainViewModel = mainViewModel;
        }
    }
}

SearchView.xaml

<UserControl x:Class="ExampleProject.Views.SearchView"
             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:local="clr-namespace:ExampleProject.Views"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <TextBlock Text="Search View"
                   FontSize="32"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Center" />
    </Grid>
</UserControl>

SearchView.xaml(代码隐藏)

namespace ExampleProject.Views
{
    /// <summary>
    /// Logic of interaction for SearchtView.xaml
    /// </summary>
    public partial class SearchView : UserControl
    {
        public SearchView()
        {
            InitializeComponent();
        }
    }
}

谢谢。

【问题讨论】:

    标签: c# xaml mvvm data-binding mahapps.metro


    【解决方案1】:

    PropertyChangedViewModel 没有myGlobalVarMainViewModel 有。

    您必须将mainViewModel 转换为MainViewModel,因为mainViewModel 的类型为PropertyChangedViewModel 而不是MainViewModel

    ((MainViewModel)mainViewModel).myGlobalVar = ...
    

    这就是为什么尊重“命名约定”非常重要的原因,如果你没有以错误的类命名它,你就不会将它与另一个类混淆。

    此外,为了使绑定起作用,类成员必须是公共属性,否则无法从 XAML 访问它,并且不会显示在 XAML 智能感知中。

    如果您不想公开,则必须改用DependencyProperty

    【讨论】:

    • 谢谢!我试过了,现在我可以访问每个视图模型中的属性。我尝试将此属性绑定到标签,但不起作用。我试过&lt;Label Content="{Binding Path=_mainViewModel.myGlobalVar} /&gt;"&lt;Label Content="{Binding _mainViewModel.myGlobalVar}" 什么都没有...如何绑定到属性?
    • 我也试过了:public string message;this.message = _mainViewModel.myGlobalVar; 并与 &lt;Label Content="{Binding message} /&gt;" 绑定,两者都没有......
    • @Randolf 那是因为您绑定的是字段而不是属性。此外,您必须提供一种方法来通知视图您对视图模型所做的更改,否则它将是一次性绑定。这太基本且太长,无法在这里解释。
    • @Randolf,只是为了给你一些线索,从类成员“只有公共属性”出现在 XAML 和 DPs 中。并遵循该示例中MenuOptionItems 的模式
    • 我认为当从PropertyChangedViewModel 类派生时,我不必遵循与MenuOptionItems 相同的模式并在每个集合中调用OnPropertyChanged (); ... 那么那个接口是什么如果我必须手动拨打OnPropertyChanged () ;
    猜你喜欢
    • 2012-08-14
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-14
    相关资源
    最近更新 更多