本文介绍了View,ViewModel和DataContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了解决我的应用程序中的导航问题,我使用了Event Aggregator(事件聚合器),它可以解决该问题,但是又创建了另一个.

要在不同的UserControls之间导航,我使用了Rachel的代码,您可以找到在这里,在我进行了一些更改之前,一切正常.

在屏幕的一侧,我有一个主菜单(HomeViewModel()),通过单击在UserControl之间切换的项目,在每个UserControl中都有另一个菜单栏,可在其中切换其他UserControl. /p>

但是第二个菜单(CateringMenuViewModel())不再起作用.显示了UserControl,但单击菜单栏中没有任何反应.

乍一看,我认为这是因为没有DataContext.因此,我将其添加到了如下代码中:

public CateringMenuView()
{
    InitializeComponent();
    this.DataContext = new CateringMenuViewModel(ApplicationService.Instance.EventAggregator);
}

但是它仍然不起作用.

我不明白,属性Name有很好的边界,因为名称显示在菜单中,但命令ChangePageCommand却没有.

HomeViewModel

public class HomeViewModel : ObservableObject
{
    #region Fields

    private ICommand _changePageCommand;
    private IPageViewModel _currentPageViewModel;
    private List<IPageViewModel> _pageViewModels;

    #endregion

    public HomeViewModel()
    {
        // Add available pages
        PageViewModels.Add(new HomeOrderViewModel());
        PageViewModels.Add(new CateringMenuViewModel(ApplicationService.Instance.EventAggregator));
        PageViewModels.Add(new HomeAdminViewModel());


        // Set starting page
        CurrentPageViewModel = PageViewModels[0];
    }

    #region Properties / Commands
}

CateringMenuViewModel

public class CateringMenuViewModel : ObservableObject, IPageViewModel
{

    protected readonly IEventAggregator _eventAggregator;

    public CateringMenuViewModel(IEventAggregator eventAggregator)
    {
        this._eventAggregator = eventAggregator;

        PageViewModels.Add(new NewRegularOrderViewModel(ApplicationService.Instance.EventAggregator));
        PageViewModels.Add(new NewDeliveryComOrderViewModel());

        PageViewModels2.Add(new FillOrderViewModel());

        // Set starting page
        CurrentUserControl = PageViewModels[0];

        this._eventAggregator.GetEvent<GoToFillOrder>().Subscribe(GoToFillOrder);

    }

    public string Name
    {
        get
        {
            return "Catering";
        }
    }

    public string imageSource
    {
        get
        {
            return "catering.ico";
        }
    }

    #region Fields

    private List<IUserContentViewModel> _pageViewModels;
    public List<IUserContentViewModel> PageViewModels
    {
        get
        {
            if (_pageViewModels == null)
                _pageViewModels = new List<IUserContentViewModel>();

            return _pageViewModels;
        }
    }

    private IUserContentViewModel _currentUserControl;
    public IUserContentViewModel CurrentUserControl
    {
        get { return _currentUserControl; }
        set
        {
            if (value != _currentUserControl)
            {
                _currentUserControl = value;
                OnPropertyChanged("CurrentUserControl");
            }
        }
    }

    #region Methods

    private void ChangeViewModel(IUserContentViewModel viewModel)
    {
        if (!PageViewModels.Contains(viewModel))
            PageViewModels.Add(viewModel);

        CurrentUserControl = PageViewModels
            .FirstOrDefault(vm => vm == viewModel);

        var x = this.GetHashCode();
    }

    #endregion

    private ICommand _changePageCommand;
    #endregion
    public ICommand ChangePageCommand
    {
        get
        {
            if (_changePageCommand == null)
            {
                _changePageCommand = new RelayCommand(
                    p => ChangeViewModel((IUserContentViewModel)p),
                    p => p is IUserContentViewModel);
            }

            return _changePageCommand;
        }
    }

    private void GoToFillOrder(int i)
    {
        CurrentUserControl = PageViewModels2[0];
    }

}

CateringMenuView

 <UserControl.Resources>
    <DataTemplate DataType="{x:Type cvm:NewDeliveryComOrderViewModel}">
        <cv:NewDeliveryComOrderView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type cvm:NewRegularOrderViewModel}">
        <cv:NewRegularOrderView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type cvm:FillOrderViewModel}">
        <cv:FillOrderView/>
    </DataTemplate>
</UserControl.Resources>

<Grid  Margin="5">
        <Grid>
            <StackPanel>
                <Menu>
                    <MenuItem Header="New Order">
                        <ItemsControl ItemsSource="{Binding PageViewModels}" Width="168" >
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock>
                                        <Hyperlink Command="{Binding ChangePageCommand, Mode=OneWay}" CommandParameter="{Binding}" TextDecorations="{x:Null}">
                                            <InlineUIContainer>
                                                <TextBlock Text="{Binding Name}"/>
                                            </InlineUIContainer>
                                        </Hyperlink>
                                    </TextBlock>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </MenuItem>
                </Menu>
            </StackPanel>
        </Grid>

   <ContentControl Content="{Binding CurrentUserControl}"/>

</Grid>
解决方案

我终于找到了解决方案.

CateringMenuView()中,我替换了

<Hyperlink Command="{Binding ChangePageCommand, Mode=OneWay}"
           CommandParameter="{Binding}"
           TextDecorations="{x:Null}">

作者

<Hyperlink Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
            CommandParameter="{Binding}"
            TextDecorations="{x:Null}">

非常感谢Rachel!

In order to solve a navigation issue in my application I have used an Event Aggregator which has solved the problem but has created an other one.

To navigate between different UserControls I used the Rachel's code you can find here which was working fine until I made some changes.

On the side of my screen I have a Main Menu (HomeViewModel()), by clicking on the items I switch between UserControls and in each of these UserControls there is a another menu bar where I can switch between other UserControls.

But this second menu (CateringMenuViewModel()) doesn't work anymore. The UserControl is displayed but nothing is happening when I am clicking in the menu bar.

At the first sight I thought it's because there is no DataContext.So I added it in the code behind like this:

public CateringMenuView()
{
    InitializeComponent();
    this.DataContext = new CateringMenuViewModel(ApplicationService.Instance.EventAggregator);
}

But it still doesn't work.

I don't understand, the property Name is well bounded because the names are displayed in the menu but the command ChangePageCommand is not.

HomeViewModel

public class HomeViewModel : ObservableObject
{
    #region Fields

    private ICommand _changePageCommand;
    private IPageViewModel _currentPageViewModel;
    private List<IPageViewModel> _pageViewModels;

    #endregion

    public HomeViewModel()
    {
        // Add available pages
        PageViewModels.Add(new HomeOrderViewModel());
        PageViewModels.Add(new CateringMenuViewModel(ApplicationService.Instance.EventAggregator));
        PageViewModels.Add(new HomeAdminViewModel());


        // Set starting page
        CurrentPageViewModel = PageViewModels[0];
    }

    #region Properties / Commands
}

CateringMenuViewModel

public class CateringMenuViewModel : ObservableObject, IPageViewModel
{

    protected readonly IEventAggregator _eventAggregator;

    public CateringMenuViewModel(IEventAggregator eventAggregator)
    {
        this._eventAggregator = eventAggregator;

        PageViewModels.Add(new NewRegularOrderViewModel(ApplicationService.Instance.EventAggregator));
        PageViewModels.Add(new NewDeliveryComOrderViewModel());

        PageViewModels2.Add(new FillOrderViewModel());

        // Set starting page
        CurrentUserControl = PageViewModels[0];

        this._eventAggregator.GetEvent<GoToFillOrder>().Subscribe(GoToFillOrder);

    }

    public string Name
    {
        get
        {
            return "Catering";
        }
    }

    public string imageSource
    {
        get
        {
            return "catering.ico";
        }
    }

    #region Fields

    private List<IUserContentViewModel> _pageViewModels;
    public List<IUserContentViewModel> PageViewModels
    {
        get
        {
            if (_pageViewModels == null)
                _pageViewModels = new List<IUserContentViewModel>();

            return _pageViewModels;
        }
    }

    private IUserContentViewModel _currentUserControl;
    public IUserContentViewModel CurrentUserControl
    {
        get { return _currentUserControl; }
        set
        {
            if (value != _currentUserControl)
            {
                _currentUserControl = value;
                OnPropertyChanged("CurrentUserControl");
            }
        }
    }

    #region Methods

    private void ChangeViewModel(IUserContentViewModel viewModel)
    {
        if (!PageViewModels.Contains(viewModel))
            PageViewModels.Add(viewModel);

        CurrentUserControl = PageViewModels
            .FirstOrDefault(vm => vm == viewModel);

        var x = this.GetHashCode();
    }

    #endregion

    private ICommand _changePageCommand;
    #endregion
    public ICommand ChangePageCommand
    {
        get
        {
            if (_changePageCommand == null)
            {
                _changePageCommand = new RelayCommand(
                    p => ChangeViewModel((IUserContentViewModel)p),
                    p => p is IUserContentViewModel);
            }

            return _changePageCommand;
        }
    }

    private void GoToFillOrder(int i)
    {
        CurrentUserControl = PageViewModels2[0];
    }

}

CateringMenuView

 <UserControl.Resources>
    <DataTemplate DataType="{x:Type cvm:NewDeliveryComOrderViewModel}">
        <cv:NewDeliveryComOrderView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type cvm:NewRegularOrderViewModel}">
        <cv:NewRegularOrderView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type cvm:FillOrderViewModel}">
        <cv:FillOrderView/>
    </DataTemplate>
</UserControl.Resources>

<Grid  Margin="5">
        <Grid>
            <StackPanel>
                <Menu>
                    <MenuItem Header="New Order">
                        <ItemsControl ItemsSource="{Binding PageViewModels}" Width="168" >
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock>
                                        <Hyperlink Command="{Binding ChangePageCommand, Mode=OneWay}" CommandParameter="{Binding}" TextDecorations="{x:Null}">
                                            <InlineUIContainer>
                                                <TextBlock Text="{Binding Name}"/>
                                            </InlineUIContainer>
                                        </Hyperlink>
                                    </TextBlock>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </MenuItem>
                </Menu>
            </StackPanel>
        </Grid>

   <ContentControl Content="{Binding CurrentUserControl}"/>

</Grid>
解决方案

I finally found the solution.

In CateringMenuView(), I have replaced

<Hyperlink Command="{Binding ChangePageCommand, Mode=OneWay}"
           CommandParameter="{Binding}"
           TextDecorations="{x:Null}">

by

<Hyperlink Command="{Binding DataContext.ChangePageCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
            CommandParameter="{Binding}"
            TextDecorations="{x:Null}">

Big thanks to Rachel!

这篇关于View,ViewModel和DataContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 10:55
查看更多