我有一个案例,稍微复杂一点,但我尝试说明并做一些修改以简单的方式说明问题所在。

假设我有一个Window1作为 View ,一个Window1ViewModel作为它的 View 模型。我还有一个SubMenuViewModel类来表示窗口中的子菜单。我想在包含许多子菜单的Window1中创建一个ItemsControl。每次用户单击子菜单之一时,属性CurrentSubMenu都会更新为相应的子菜单。这是问题,我无法在Window1ViewModel中更新CurrentSubMenu。



SubMenuViewModel:

public class SubMenuViewModel : INPC
    {
        private string _submenuname;
        public string SubMenuName
        {
            get
            {   return _submenuname;   }
            set
            {
                _submenuname = value;
                RaisePropertyChanged("SubMenuName");
            }
        }
        private string _displayname;
        public string DisplayName
        {
            get
            {   return _displayname;   }
            set
            {
                _displayname = value;
                RaisePropertyChanged("DisplayName");
            }
        }

        // Command for Hyperlink in ItemsControl //
        private RelayCommand _commandSubmenu;
        public RelayCommand CommandSubMenu
        {
            get
            {   return _commandSubmenu;   }
            set
            {
                _commandSubmenu = value;
                RaisePropertyChanged("CommandSubMenu");
            }
        }
        // end of command

        public SubMenuViewModel(string Submenu_name, string Display_name)
        {
            _submenuname = Submenu_name;
            _displayname = Display_name;
        }
    }

窗口1:
<Window x:Class="SomeProject.Window1"
        xmlns:vm="clr-namespace:SomeProject.ViewModel"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="This is Some Project" WindowState="Maximized">
    <Window.DataContext>
        <vm:Window1ViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="250" />
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Border Name="SubMenuPanelBorder"
                Grid.Column="0"
                Grid.Row="1"
                HorizontalAlignment="Stretch"
                VerticalAlignment="Stretch"
                Margin="15 0 15 0"
                BorderThickness="2"
                BorderBrush="Black"
                Padding="10 10">

            <HeaderedContentControl Content="{Binding Path=SubMenus}" Header="Panel Submenu :">
                <HeaderedContentControl.ContentTemplate>
                    <DataTemplate>
                        <ItemsControl ItemsSource="{Binding}" Foreground="White" Background="Transparent" Margin="0 15">
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock>
                                        <Hyperlink Command="{Binding Path=CommandSubMenu}">
                                            <TextBlock Margin="0 5" Text="{Binding Path=DisplayName}"/>
                                        </Hyperlink>
                                    </TextBlock>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </DataTemplate>
                </HeaderedContentControl.ContentTemplate>
            </HeaderedContentControl>

        </Border>

        .......
        .......

    </Grid>
</Window>

Window1ViewModel:
class Window1ViewModel : INPC
    {
        private List<SubMenuViewModel> _submenus;
        public List<SubMenuViewModel> SubMenus
        {
            get
            {   return _submenus;   }
            set
            {
                _submenus = value;
                RaisePropertyChanged("SubMenus");
            }
        }
        private SubMenuViewModel _currentSubMenu;
        public SubMenuViewModel CurrentSubMenu
        {
            get
            {   return _currentSubMenu;    }
            set
            {
                _currentSubMenu = value;
                RaisePropertyChanged("CurrentSubMenu");
            }
        }

        public Window1ViewModel()
        {
            SubMenus = MenuDefinition.GetSubMenus();

            /***
            Set the SubMenus's command to update the CurrentSubMenu,
            and == HERE IS WHERE I GOT LOST ==.
            The CurrentSubMenu is always point to the last submenu in the loop when clicked.

            By the way, the reason I use loop is because the submenu in the Menu definition sometimes changed and there are many number of submenus there, and there are some other reasons (I use Menu-submenu mechanism, but it's not essential to show it here because it's not the main point I want to show). So, finally I use loop instead of specifying each command one by one.
            ***/

            foreach(SubMenuViewModel submenu in SubMenus){
                submenu.CommandSubMenu=new RelayCommand(()=>clickedSubMenu(submenu.SubMenuName));
            }
        }

        public void clickedSubMenu(string submenu_name)
        {
            CurrentSubMenu = SubMenus.Find(sub => sub.SubMenuName == submenu_name);
        }
    }

菜单定义:
public static List<SubMenuViewModel> GetSubMenus()
        {
            return new List<SubMenuViewModel>
                    {
                        new SubMenuViewModel("overview_product", "Overview Products"),
                        new SubMenuViewModel("search_product","Search Products"),
                        new SubMenuViewModel("update_product","Update Data Products"),
                        new SubMenuViewModel("order_product","Order Products"),
                        new SubMenuViewModel("supplier_product","Products Supplier"),
                        .................
                        .................
                        .................
                    };
            }
        }

最佳答案

我相信您的绑定(bind)属性应这样写。

private string _Terminal;
    public string Terminal
    {
        get
        {
            return _Terminal;
        }
        set
        {
            _Terminal = value;
            OnPropertyChanged("Terminal");
        }
    }

确保viewmodel实现INotifyPropertyChanged
public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
{
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if (propertyChanged != null)
        {
            PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);
            propertyChanged(this, e);
        }
    }

关于c# - WPF MVVM案例: ItemsControl contains hyperlink and command to update property in ViewModel,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19148850/

10-12 14:51