【问题标题】:Dynamically adding user controls based on radio button selection - WPF基于单选按钮选择动态添加用户控件 - WPF
【发布时间】:2014-08-01 13:07:25
【问题描述】:

我正在寻找一种基于单选按钮选择动态加载用户控件的解决方案。问题在下面解释。 1. 我有一个基本窗口 xaml (MainWindow)。这有 2 个堆栈面板,SP1 和 SP2。
2. 我创建了 5 个用户控件 2.1 Radio UC ==> 4 个单选按钮。 2.2 选项 1 UC 2.3 选项 2 UC 2.4 选项 3 UC 2.5 选项4 UC

  1. Radio UC 在设计时加载到 MainWindow 的 SP1 中。
  2. 根据单选按钮的选择,应在 SP2 中动态加载 4 个选项 UC 之一

我已尝试在附图中解释上述内容。

我一无所知,因为我不太了解 WPF。任何人都可以使用 WPF MVVM 模式帮助我解决这个问题。

提前致谢。

【问题讨论】:

  • 看看我对这个问题的回答(有一个指向先前答案的链接,该答案中也需要该链接)stackoverflow.com/questions/24762810/…
  • 您基本上会让 RadioButtons ViewModel 引发一个 SelectionChanged 事件,并且您的 MainViewModel 将被注册以对其进行操作。然后 MainViewModel 将为您所需的 UserControl 设置一个属性(类型 ViewModelBase)为适当的 ViewModel 类型,DataTemplates 将自动更改 UI。
  • 这是我打算实施的那种,但我不知道如何做到这一点“引发一个 SelectionChanged 事件,您的 MainViewModel 将被注册以对其采取行动。然后 MainViewModel 将设置一个属性(类型 ViewModelBase)”。你能提供代码sn-p吗?谢谢。

标签: wpf


【解决方案1】:

你可以试试这样的:

在 XAML 中:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.Resources>
            <local:VisibilityConverter x:Key="visibilityConverter"  />
        </Grid.Resources>
        <StackPanel>
            <StackPanel>
                <RadioButton Content="one" GroupName="a" Name="one"/>
                <RadioButton Content="two" GroupName="a" Name="two"/>
            </StackPanel>
            <StackPanel >
                <RadioButton Content="linked to one" Visibility="{Binding ElementName=one, Path=IsChecked, Converter={StaticResource visibilityConverter}}"/>
                <RadioButton Content="linked to two" Visibility="{Binding ElementName=two, Path=IsChecked, Converter={StaticResource visibilityConverter}}"/>
            </StackPanel>            
        </StackPanel>
    </Grid>
</Window>

在代码中可见性转换器:

public class VisibilityConverter : IValueConverter
{
    object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if ((Boolean)value)
        {
            return Visibility.Visible;
        }
        else
        {
            return Visibility.Collapsed;
        }
    }

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

我确信您的 XAMl 看起来会有些不同,但概念是相同的。我希望。

【讨论】:

  • 感谢您的回复,但正如我所提到的,这可能不起作用,单选按钮来自不同的用户控件。我必须从父主窗口视图模型处理这个,我不知道。
  • 没有必要通过你的视图模型。如果您将依赖属性添加到您的用户控件。您可以将现在可见的绑定替换为您自己的自定义属性,并将选定的单选按钮信息获取到您的用户控件中。通过这种方式,您可以在视图和 XAML 级别上查看内容。在我看来更干净。
【解决方案2】:

在您的 MainViewModel 中创建一个属性来保存 RadioControlViewModel,并创建一个属性来保存选定的 OptionViewModel。在您的构造函数中,注册 RadioControlViewModel 的 OptionSelectionChanged 事件。 EventHandler 方法应将 OptionViewModel 的值更改为 ViewModel 的实例,该实例表示您希望为该选择显示的控件。代码中声明“etcetera”的所有 cmets 表示为选项 3 和 4 添加相同的前面代码。

MainViewModel

public class MainViewModel
{
    private RadioControlViewModel _rcViewModel;
    public RadioControlViewModel RcViewModel
    {
       get { return _rcViewModel; }
       set
       {
          _rcViewModel = value;
          RaisePropertyChanged("RcViewModel");
       }
    }

    private OptionViewModelBase _optionViewModel;
    public OptionViewModelBase OptionViewModel
    {
       get { return _optionViewModel; }
       set
       {
          _optionViewModel = value;
          RaisePropertyChanged("OptionViewModel");
       }
    }

    public MainViewModel()
    {
       RcViewModel = new RadioControlViewModel();
       RcViewModel.OptionSelectionChanged += RcViewModel_OptionSelectionChanged;
    }

    private void RcViewModel_OptionSelectionChanged(object sender, OptionSelectionChangedEventArgs e)
    {
       if (e.Selection == null)
       {
          OptionViewModel = null;
          return;
       }

       switch (e.Selection)
       {
          case Option.OptionOne:
             OptionViewModel = new OptionOneViewModel();
             break;
          case Option.OptionTwo:
             OptionViewModel = new OptionTwoViewModel();
             break;
          // etcetera
       }
    }
 }

在您的 MainView.Resources 中,您将放置 DataTemplates,将每个 OptionViewModel 映射到相应的 OptionView。第一个 StackPanel 将 RadioControlView 的 DataContext 绑定到 MainViewModel 的 RadioControlViewModel 属性。在第二个 StackPanel 中,您使用 ContentPresenter 并将 Content 属性绑定到 MainViewModel 的 OptionViewModel 属性。 DataTemplates 会告诉它如何呈现这个。

主视图

 <Window.Resources>
    <DataTemplate DataType="{x:Type viewmodel:OptionOneViewModel}">
       <view:OptionOneView />
    </DataTemplate>

    <DataTemplate DataType="{x:Type viewmodel:OptionTwoViewModel}">
       <view:OptionTwoView />
    </DataTemplate>

    <!-- etcetera -->
 </Window.Resources>

 <Grid>
    <StackPanel>
       <view:RadioControlView DataContext="{Binding RcViewModel}" />
    </StackPanel>
    <StackPanel>
       <ContentPresenter Content="{Binding OptionViewModel}" />
    </StackPanel>
 </Grid>

RadioControlViewModel 将有一个 OptionSelectionChanged 事件,只要其中一个绑定的 RadioButton 将其属性设置为 true,就会引发该事件。

RadioControlViewModel

public class RadioControlViewModel
{
   public event EventHandler<OptionSelectionChangedEventArgs> OptionSelectionChanged;

   private bool _optionOneSelected;
   public bool OptionOneSelected
   {
      get { return _optionOneSelected; }
      set
      {
         _optionOneSelected = value;
         RaisePropertyChanged("OptionOneSelected");
         if (value)
            RaiseOptionSelectionChanged(Option.OptionOne);
      }
   }

   private bool _optionTwoSelected;
   public bool OptionTwoSelected
   {
      get { return _optionTwoSelected; }
      set
      {
         _optionTwoSelected = value;
         RaisePropertyChanged("OptionTwoSelected");
         if (value)
            RaiseOptionSelectionChanged(Option.OptionTwo);
      }
   }

   // etcetera

   private void RaiseOptionSelectionChanged(Option selection)
   {
      var handler = OptionSelectionChanged;
      if (handler == null)
         return;

      handler(this, new OptionSelectionChangedEventArgs(selection));
   }
}

前面的代码假设您将创建一个 OptionSelectionChangedEventArgs 类并拥有一个名为 Option 的枚举。需要进行一些调整,例如您的 MainViewModel 构造函数可能希望将 OptionViewModel 属性设置为将初始化为选中的选项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-08
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    • 1970-01-01
    相关资源
    最近更新 更多