TabControl을 ViewModel 컬렉션에 어떻게 바인딩합니까?
기본적으로 MainViewModel.cs에 있습니다.
ObservableCollection<TabItem> MyTabs { get; private set; }
그러나 어떻게 든 탭을 만들 수있을뿐만 아니라 MVVM을 유지하면서 탭 내용을로드하고 적절한 뷰 모델에 연결할 수 있어야합니다.
기본적으로 사용자 컨트롤을 탭 항목의 콘텐츠로로드하고 해당 사용자 컨트롤을 적절한 뷰 모델에 연결하려면 어떻게해야합니까? 이를 어렵게 만드는 부분은 ViewModel이 실제 뷰 항목을 구성해서는 안된다는 것입니다. 아니면 할 수 있습니까?
기본적으로 MVVM이 적절할까요?
UserControl address = new AddressControl();
NotificationObject vm = new AddressViewModel();
address.DataContext = vm;
MyTabs[0] = new TabItem()
{
Content = address;
}
나는 MVVM no-no처럼 들리는 ViewModel 내에서 View (AddressControl)를 구성하고 있기 때문에 묻습니다.
이것은 MVVM이 아닙니다. 뷰 모델에서 UI 요소를 생성하지 않아야합니다.
Tab의 ItemsSource를 ObservableCollection에 바인딩해야하며 생성해야하는 탭에 대한 정보가있는 모델을 보유해야합니다.
다음은 탭 페이지를 나타내는 VM 및 모델입니다.
public sealed class ViewModel
{
public ObservableCollection<TabItem> Tabs {get;set;}
public ViewModel()
{
Tabs = new ObservableCollection<TabItem>();
Tabs.Add(new TabItem { Header = "One", Content = "One's content" });
Tabs.Add(new TabItem { Header = "Two", Content = "Two's content" });
}
}
public sealed class TabItem
{
public string Header { get; set; }
public string Content { get; set; }
}
다음은 창에서 바인딩이 어떻게 보이는지입니다.
<Window x:Class="WpfApplication12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<ViewModel
xmlns="clr-namespace:WpfApplication12" />
</Window.DataContext>
<TabControl
ItemsSource="{Binding Tabs}">
<TabControl.ItemTemplate>
<!-- this is the header template-->
<DataTemplate>
<TextBlock
Text="{Binding Header}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<!-- this is the body of the TabItem template-->
<DataTemplate>
<TextBlock
Text="{Binding Content}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Window>
(참고, 다른 탭에서 다른 항목을 원하면을 사용하십시오 DataTemplates
. 각 탭의보기 모델은 자체 클래스 여야하거나 DataTemplateSelector
올바른 템플릿을 선택 하는 사용자 지정 을 만들어야합니다 .)
오보세요, 데이터 템플릿 내부의 UserControl :
<TabControl
ItemsSource="{Binding Tabs}">
<TabControl.ItemTemplate>
<!-- this is the header template-->
<DataTemplate>
<TextBlock
Text="{Binding Header}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<!-- this is the body of the TabItem template-->
<DataTemplate>
<MyUserControl xmlns="clr-namespace:WpfApplication12" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
Prism에서는 일반적으로 탭 컨트롤을 영역으로 만들어서 바인딩 된 탭 페이지 컬렉션을 제어 할 필요가 없습니다.
<TabControl
x:Name="MainRegionHost"
Regions:RegionManager.RegionName="MainRegion"
/>
이제 MainRegion 영역에 자신을 등록하여 뷰를 추가 할 수 있습니다.
RegionManager.RegisterViewWithRegion( "MainRegion",
( ) => Container.Resolve<IMyViewModel>( ).View );
And here you can see a speciality of Prism. The View is instanciated by the ViewModel. In my case I resolve the ViewModel throught a Inversion of Control container (e.g. Unity or MEF). The ViewModel gets the View injected via constructor injection and sets itself as the View's data context.
The alternative is to register the view's type into the region controller:
RegionManager.RegisterViewWithRegion( "MainRegion", typeof( MyView ) );
Using this approach allows you to create the views later during runtime, e.g. by a controller:
IRegion region = this._regionManager.Regions["MainRegion"];
object mainView = region.GetView( MainViewName );
if ( mainView == null )
{
var view = _container.ResolveSessionRelatedView<MainView>( );
region.Add( view, MainViewName );
}
Because you have registered the View's type, the view is placed into the correct region.
I have a Converter to decouple the UI and ViewModel,thats the point below:
<TabControl.ContentTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Tab,Converter={StaticResource TabItemConverter}"/>
</DataTemplate>
</TabControl.ContentTemplate>
The Tab is a enum in my TabItemViewModel and the TabItemConverter convert it to the real UI.
In the TabItemConverter,just get the value and Return a usercontrol you need.
Possibly so :
<UserControl x:Class="Test_002.Views.MainView"
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:local="clr-namespace:Test_002.Views"
xmlns:generalView="clr-namespace:Test_002.Views.General"
xmlns:secVIew="clr-namespace:Test_002.Views.Security"
xmlns:detailsView="clr-namespace:Test_002.Views.Details"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="650">
<Grid>
<DockPanel>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom" Margin="2,5">
<Button Command="{Binding btnPrev}" Content="Prev"/>
<Button Command="{Binding btnNext}" Content="Next"/>
<Button Command="{Binding btnSelected}" Content="Selected"/>
</StackPanel>
<TabControl>
<TabItem Header="General">
<generalView:GeneralView></generalView:GeneralView>
</TabItem>
<TabItem Header="Security">
<secVIew:SecurityView></secVIew:SecurityView>
</TabItem>
<TabItem Header="Details">
<detailsView:DetailsView></detailsView:DetailsView>
</TabItem>
</TabControl>
</DockPanel>
</Grid>
Think this is the easiest way. Is the MVVM Compatible ?
참고URL : https://stackoverflow.com/questions/5650812/how-do-i-bind-a-tabcontrol-to-a-collection-of-viewmodels
'Programing' 카테고리의 다른 글
Javascript 객체의 속성 이름을 반복하는 방법은 무엇입니까? (0) | 2020.11.17 |
---|---|
C ++ 프로젝트에서 C 스타일 캐스트를 사용하는 경우 C ++ 캐스트로 리팩토링 할 가치가 있습니까? (0) | 2020.11.17 |
Android에서 채워지지 않은 그림을 그리는 방법은 무엇입니까? (0) | 2020.11.17 |
업로드 된 파일을 디렉토리에 저장하기 전에 이름을 바꾸는 방법은 무엇입니까? (0) | 2020.11.17 |
org.hibernate.hql.internal.ast.QuerySyntaxException : 테이블이 매핑되지 않음 (0) | 2020.11.17 |