I am writing an app with a MS Office style tab ribbon on top. This tabcontrol is placed in a region in the shell which is set up by the Mef.
Code in shell.xaml:
...
<ContentControl Name="TabRegion" prism:RegionManager.RegionName="TabRegion"/>
...
Code in TabRegionView.xaml:
<UserControl x:Class="Ensor.Studio.View.TabRegionView"
etc...>
<TabControl Margin="5" BorderThickness="0" Background="White" ItemsSource="{Binding Path=Tabs}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ContentControl Content="{Binding Content}"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</UserControl>
Code in tab content: ProjectTabView.xaml
<UserControl x:Class="Ensor.Studio.View.Tabs.ProjectTabView"
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:ap="clr-namespace:Ensor.Studio.ViewModel.CustomControls"
xmlns:vm="clr-namespace:Ensor.Studio.ViewModel.Tabs"
mc:Ignorable="d"
d:DesignHeight="110" d:DesignWidth="800">
<StackPanel Orientation="Horizontal">
<Button Name="button_ProjectBrowse" Command="{Binding ProjectBrowseCommand}"
Style="{StaticResource BigTabButton}" Margin="5,10
ap:ButtonProperties.Image="pack:.../ButtonIcons/open.png"
Content="Browse"/>
<Rectangle Margin="5,10" Stroke="Silver"/>
...
When I run the app, this tabcontrol renders fine, but the usercontrols are not linked with the right view model... When the shell initializes the following error pops up in the output:
System.Windows.Data Error: 40 : BindingExpression path error: 'ProjectBrowseCommand' property not found on 'object' ''TabRegionViewModel' (HashCode=37840511)'. BindingExpression:Path=ProjectBrowseCommand; DataItem='TabRegionViewModel' (HashCode=37840511); target element is 'Button' (Name='button_ProjectBrowse'); target property is 'Command' (type 'ICommand')
Which means that the view looked for a ProjectBrowseCommand in the TabRegionViewModel, which is the viewmodel of the whole tab control, while it actually should have looked in ProjectTabViewModel.
But the app keeps running so when I click on this first tab which makes the content of this tab appear and the following error pops up:
System.Windows.Data Error: 40 : BindingExpression path error: 'ProjectBrowseCommand' property not found on 'object' ''ProjectTabView' (Name='')'. BindingExpression:Path=ProjectBrowseCommand; DataItem='ProjectTabView' (Name=''); target element is 'Button' (Name='button_ProjectBrowse'); target property is 'Command' (type 'ICommand')
Which means this time it looked for a ProjectBrowseCommand in the backend code of the view of the specific tab.
What I'm actually trying to do is link the usercontrol in the ProjectTab to ProjectTabViewModel. This is a class with multiple dependencies so I'd rather not use DataContext = new ProjectTabViewModel(...);
So my question is, why did the view look in the wrong classes to find it's bindings. And how can I hook it up to ProjectTabViewModel with Dependency Injection?
What I would do is bind the ItemsSource to a ViewModel property of eg ObservableCollection<object>
( object
can also be a base class for all tabs ViewModel).
Then use DataTemplate to tell WPF how to represents the different ViewModels:
For example likes this:
public class ViewModel
{
public ObservableCollection<object> Tabs { get; } = new ObservableCollection<object>();
public ViewModel()
{
Tabs.Add(new FirstViewModel());
}
}
<TabControl ItemsSource="{Binding Path=Tabs}"></TabControl>
Resources:
<DataTemplate DataType="{x:Type viewModels:FirstViewModel} ">
<views:FirstView/>
</DataTemplate>
UPDATE
Using dependency injection:
public class ViewModel
{
public ObservableCollection<TabViewModelBase> Tabs { get; } = new ObservableCollection<object>();
public ViewModel(IEnumerable<TabViewModelBase> tabs)
{
Tabs.Add(tabs);
}
}
public class FirstViewModel : TabViewModelBase
{
}
I assume that you know how to configure a container in the root of your application.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.