Prism と MEF を使用しています。Prism - MVVM - MEF ルールに違反することなく、タブ項目をタブ コントロールに動的に追加したいと考えています。誰かが簡単な手順/例でこれを行う方法を教えてもらえますか
3 に答える
まず第一に、私のアプローチが考えられるすべてのアプローチの中で最高であると言っているわけではありません...しかし、クールだと思うので共有したいだけです:)
TabControl領域を持つことができます...そのため、いくつかのビューでその領域に移動するだけです:) ...何が起こりますか? いくつかのビューで TabControl 領域に移動すると、そのビューが新しい TabItem として追加されます。
もちろん、最初にやらなければならないことがあります。
TabControl スタイルを変更する必要があります。TabControl に、Tab 項目のヘッダーがどこにあるかを伝えるだけで済みます。もちろん、アプリケーションのリソースに追加できます。
したがって、TabItemStyle が必要です...どこにヘッダー テキストがあるかを指定します...このようなものです...
<Style x:Key="MyTabItemStyle" TargetType="{x:Type TabItem}"> <Setter Property="Header" Value="{Binding Content.DataContext.TabHeaderText, RelativeSource={RelativeSource Self}}"/> ...
そして、デフォルトのTabControlStyleで使用します
<Style TargetType="{x:Type TabControl}"> <Setter Property="ItemContainerStyle" Value="{StaticResource MyTabItemStyle}"/> ...
これで、TabControl 領域を好きな場所に定義できるようになりました。前に定義した Style を使用する必要があることに注意してください。
<TabControl Regions:RegionManager.RegionName="MyRegion" ... />
これで、ビューを使用してその領域に移動できます...もちろん、そのビューの DataContext を文字列プロパティ TabHeaderText を持つ ViewModel に設定する必要があります...
これで動作するはずです:)もちろん、ナビゲーションについて話しているので、ビューモデルに[RegionMemberLifetime(KeepAlive = true)]
属性を提供する必要があります:)いつか誰かの役に立てば幸いです。
TabControl は、他の多くのコントロールと同様にコレクションにバインドできます。これは、チャット メッセージング プログラムにあるタブ コントロールの例です。
<TabControl ItemsSource="{Binding Path=Rooms, Mode=OneWay}" SelectedItem="{Binding Path=SelectedRoom, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=RoomName}" x:Name="Header" Tag="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
//in here is where you put controls for what you want the tabs to look like.
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
したがって、この例では、RoomName のようなプロパティを持つ「Rooms」と呼ばれるカスタム データ型「ChatRoom」のコレクションがあります。ユーザーが新しいルームを作成するたびに、そのルームが Rooms コレクションに追加され、新しいタブ項目が作成されます。だから私のviewModelで:
private ObservableCollection<ChatRoom> _Rooms;
public MainWindowViewModel()
{
this._Rooms = new ObservableCollection<ChatRoom>();
}
public ObservableCollection<ChatRoom> Rooms
{
get { return this._Rooms; }
}
TabControl にはリージョン アダプターが必要です。リボン コントロール用に作成したので、インスピレーションを得ることができます。
public class RibbonRegionAdapter : RegionAdapterBase<Ribbon>
{
public RibbonRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
: base(regionBehaviorFactory)
{
}
protected override void Adapt(IRegion region, Ribbon regionTarget)
{
region.Views.CollectionChanged += (s, e) =>
{
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
foreach (RibbonTabItem RibbonTab in e.NewItems)
{
regionTarget.Tabs.Add(RibbonTab);
}
}
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
foreach (RibbonTabItem RibbonTab in e.OldItems)
{
regionTarget.Tabs.Remove(RibbonTab);
}
}
};
}
protected override IRegion CreateRegion()
{
return new AllActiveRegion();
}
}
XAML で:<Fluent:Ribbon prism:RegionManager.RegionName="{x:Static inf:RegionNames.RibbonRegion}"/>
タブを追加するには、これが必要です:
IRegion RibbonRegion = _regionManager.Regions[RegionNames.RibbonRegion];
RibbonRegion.Add(YourTabItemView);
RegionNames は、私のインフラストラクチャ プロジェクトの単なるクラスです。
public class RegionNames
{
public static string RibbonRegion = "RibbonRegion";
}
それが役立つことを願っています