在我看来,我正在添加动态自定义TabItems(TextseiteTabItem)。使用属性DataContext,我为每个TabItem提供了一个可以使用的模型(填充值)。现在我添加了一个关闭命令到自定义TabItems但它不会工作。我无法将close命令发送到viewmodel。以上是我的尝试..
我的自定义TabItem:
<sdk:TabItem x:Class="PortfolioCreator.TextseiteTabItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
<sdk:TabItem.Header>
<StackPanel Orientation="Horizontal">
<sdk:Label Content="{Binding Seitennummer, StringFormat='Seite {0}', Mode=TwoWay}"/>
<Button Content="X"
Command="{Binding CloseTabCommand, Mode=TwoWay}"
DataContext="{Binding ElementName=TemplateTabControl}"
CommandParameter="{Binding SelectedItem, ElementName=TemplateTabControl}" />
</StackPanel>
</sdk:TabItem.Header>
<sdk:TabItem.Content>
<Grid x:Name="LayoutRoot">
...
</Grid>
</sdk:TabItem.Content>
</sdk:TabItem>
在我的观点中:
...
<sdk:TabControl toolkit:DockPanel.Dock="Bottom" ItemsSource="{Binding Tabs}" x:Name="TemplateTabControl"/>
...
在我的ViewModel中:
public class PortfolioViewModel : ViewModelBase
{
public ObservableCollection<TabItem> Tabs { get; set; }
public RelayCommand<TabItem> CloseTabCommand
{
get;
private set;
}
public PortfolioViewModel()
{
CloseTabCommand = new RelayCommand<TabItem>(tab =>
{
//never reached
},
tab =>
{
//never reached
});
Tabs = new ObservableCollection<TabItem>();
AddTextseite();
AddTextseite();
}
void AddTextseite()
{
TabItem item = new TextseiteTabItem();
item.DataContext = new TextSeiteModel();
Tabs.Add(item);
}
}
答案 0 :(得分:1)
您正在尝试使用MVVM,但我看到的奇怪之处是视图模型中的ui元素(Tabs)集合。正确的方法是创建描述Tab项的ViewModel并在那里移动命令。然后它会绑定。要从Tabs中删除选项卡,您应该在Tab视图模型中公开事件,并从PortfolioViewModel附加到它。
当然,我的更改将导致TextseiteTabItem不会显示在TablControl中。但是可以使用TabControl.ItemTemplate和TabControl.ContentTemplate轻松修复它。
答案 1 :(得分:1)
首先,您的CloseTabCommand
在您当前的代码段中不执行任何操作://never reached
。执行处理程序应该读取类似tab.Visibility = Visibility.Collapsed
或myTabControl.Items.Remove(myTabItem)
的内容。
其次,正如@Rafal指出的那样,在ViewModel中使用UI元素并不是实现MVVM的正确方法。如果您想要可关闭的选项卡项,正确的方法是派生通用CloseableTabItem
控件或在UI层上编写ClosableTabItemBehavior
,并使用可设置为ICommand CloseCommand
的{{1}}绑定到相应的{ ViewModel上的{1}}实例。不可否认,这种方法可能对您的项目来说过于精细。
答案 2 :(得分:0)
here你找到一个带有关闭wpf标签的演示应用程序,也许它适用于你的silverlight版本。
答案 3 :(得分:0)
这是我解决此问题的方法。我承认这不是一个好的解决方案,打破了mvvm模式,但正如@herzmeister所说,其他方法现在对我的项目来说太复杂了。 (但它不是最终的解决方案;-))
TabItemViewModel:
public delegate void CloseTabItemHandler();
public class TextseiteTabItemViewModel : ViewModelBase
{
public event CloseTabItemHandler CloseTabItem;
public RelayCommand CloseTabCommand {get; set;}
public TextseiteTabItemViewModel()
{
CloseTabCommand = new RelayCommand(() =>
{
if (CloseTabItem == null) return;
CloseTabItem();
});
}
}
TabItemView:
<sdk:TabItem x:Class="PortfolioCreator.TextseiteTabItemView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit">
<sdk:TabItem.Header>
<StackPanel Orientation="Horizontal">
<Button Content="X" Command="{Binding CloseTabCommand, Mode=TwoWay}" />
</StackPanel>
</sdk:TabItem.Header>
<sdk:TabItem.Content>
<Grid x:Name="LayoutRoot">
...
</Grid>
</sdk:TabItem.Content>
</sdk:TabItem>
父ViewModel:
public class PortfolioViewModel : ViewModelBase
{
public ObservableCollection<TabItem> Tabs { get; set; }
public PortfolioViewModel()
{
Tabs = new ObservableCollection<TabItem>();
AddTextseite();
AddTextseite();
}
void AddTextseite()
{
var viewmodel = new TextseiteTabItemViewModel();
TabItem item = new TextseiteTabItemView();
item.DataContext = viewmodel;
viewmodel.CloseTabItem += new CloseTabItemHandler(() =>
{
Tabs.Remove(item);
});
Tabs.Add(item);
}
}