【问题标题】:Is it possible to load and unload usercontrol using triggers only in WPF是否可以仅在 WPF 中使用触发器加载和卸载用户控件
【发布时间】:2014-08-28 15:26:57
【问题描述】:

我正在尝试创建 MDI 类型的功能,我想加载与用户单击的按钮相对应的用户控件并卸载其余部分。每个按钮都与一个用户控件相关联

<Button Content="Worker registration"/> //UserControl1
<Button Content="Worker recognition"/>  //UserControl2 ...and so on

<Grid x:Name="UserControlManager"/>

【问题讨论】:

    标签: wpf


    【解决方案1】:

    有什么理由不使用选项卡控件?像这样

    <TabControl>
        <TabItem Header="Control A">
            <local:ControlA/>
        </TabItem>
        <TabItem Header="Control B">
            <local:UserControlB/>
        </TabItem>
    </TabControl>
    

    或使用 ItemsSource 绑定所有项目

    <TabControl ItemsSource="{Binding MyItems}"/>
    

    还有第三方 TabControls 非常好,就像 devcomponents 提供的一样。 如果 TabControl 不够用(我知道很多问题),您可以使用 IValueConverter 将某些属性转换为视图。您可以使用 Mediator 和/或 ViewModelLocator,我喜欢 Galasoft 的 MVVM Light。他们通过 nuget 提供一切,甚至为您设置一切:)

    为您的按钮添加一个命令,用于选择您要显示的内容。并添加用于显示 SelectedControl 的 xaml。

    Bad mediator / ViewmodelLocator ;) 使用 I.E. Galasofts 改为 like in this post

    public class ViewModelLocator : INotifyPropertyChanged
    {
        private UserControl selectedControl;
        private ObservableCollection<UserControl> controls = new ObservableCollection<UserControl>();
        public UserControl SelectedControl
        {
            get { return selectedControl; }
            set 
            {
                if (Equals(selectedControl, value)) return;
                selectedControl = value;
                OnPropertyChanged();
            }
        }
        public ObservableCollection<UserControl> Controls
        {
            get { return controls; }
            set
            {
                if (Equals(controls, value)) return;
                controls = value;
                OnPropertyChanged();
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    希望对你有帮助!

    干杯

    斯蒂安

    【讨论】:

    • 我不想在编译时加载所有用户控件,因为有很多元素从数据库中绑定。那我为什么要加载它们,即使用户可能永远不会打开它。早些时候我使用 TabControl 并由于这个原因将其删除。另外,我希望在 UI 方面有更大的灵活性
    • 虽然我现在没有使用 ViewModel,但我喜欢你的解决方案。但是你给了我一个方法:) +1。我仍在考虑可能的解决方案。
    • 啊动态xaml,那你不能使用UserControl,你必须从IE继承。网格(代码隐藏)。除此之外,看看使用中介或偏好。 ViewModelLocator.
    【解决方案2】:

    您可以使用 DataTemplates 根据您设置的数据 (viweModel) 加载视图

    <Window.Resources>
        <ResourceDictionary>
            <DataTemplate DataType="{x:Type viewModel:ViewModel1}">
                <view:View1 />
            </DataTemplate>
            <DataTemplate DataType="{x:Type viewModel:ViewModel2}">
                <view:View2 />
            </DataTemplate>
        </ResourceDictionary>
    </Window.Resources>
    

    然后有一个 ContentControl 将显示您的内容

    <Grid >
        <ContentControl Content="{Binding MyContent}" />
    </Grid
    

    使用 enumBooleanConverter (How to bind RadioButtons to an enum?) 选择带有单选按钮的枚举

    <RadioButton GroupName="Navigation" 
             IsChecked="{Binding Path=SelectedNavigationEnum, 
                          Converter={StaticResource enumBooleanConverter},
                          ConverterParameter={x:Static viewModel:NavigationEnum.EnumValue1},
                          Mode=TwoWay}">Show View1</RadioButton>
    
    
    <RadioButton GroupName="Navigation" 
             IsChecked="{Binding Path=SelectedNavigationEnum, 
                          Converter={StaticResource enumBooleanConverter},
                          ConverterParameter={x:Static viewModel:NavigationEnum.EnumValue2},
                          Mode=TwoWay}">Show View2</RadioButton>
    

    当 SelectedNavigationEnum 属性更改时,将 MyContent 属性设置为选定的 viewModel

    public NavigationEnum SelectedNavigationEnum
    {
       ...
       set
       {
          ...  
          Navigate(value);
    
       }
    }
    
    protected void Navigate(NavigationEnum part)
    {
        switch (part)
        {
            case NavigationEnum.EnumValue1:
                ShowView1();
                break;
            case NavigationEnum.EnumValue2:
                ShowView2();
            ...
        }
    }
    
    private void ShowView1()
    {
        ViewModel1 viewModel = ObjectFactory.GetInstance<ViewModel1>();
        MyContent = viewModel;
    }
    

    当您设置 MyContent 时,DataTemplate 将加载 View1 并将 viewModel 设置为其 DataContext。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-08-05
      • 1970-01-01
      • 1970-01-01
      • 2021-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多