【问题标题】:Caliburn.Micro & Telerik WPF ControlsCaliburn.Micro 和 Telerik WPF 控件
【发布时间】:2023-07-07 18:33:01
【问题描述】:

希望你一切都好。

我正在使用带有 Telerik 的 WPF 控件的 Caliburn.Micro 来构建一个选项卡式界面。使用 RadTabControl 我有以下代码;

<telerik:RadTabControl x:Name="Items" Grid.Row="1" TabStripPlacement="Bottom">
    <telerik:RadTabControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <Image Source="{Binding DisplayIcon}" Width="16" Height="16"/>
                <TextBlock Text="{Binding DisplayName}"/>
            </StackPanel>
        </DataTemplate>
    </telerik:RadTabControl.ItemTemplate>
</telerik:RadTabControl>

该选项卡具有正确的标题,但内容为“.../MyViewModel”(省略号替换完整路径)而不是应显示的屏幕。

如果我用&lt;TabControl... 替换&lt;telerik:RadTabControl...,这一切都按预期工作。

我错过了什么?

【问题讨论】:

    标签: c# wpf xaml telerik caliburn.micro


    【解决方案1】:

    Caliburn 的约定系统仅针对开箱即用的 WPF 控件进行配置。当它看到 RabTabControl 时,它无法识别它,因此它搜索它的类层次结构以寻找它可以识别的东西。在这种情况下,它可能匹配 Selector 或 ItemsControl。这就是为什么部分应用约定的原因。为了得到你想要的,你需要为 RadTabControl 的 ConventionManager 添加一个约定,它可以完全满足你的需要。以下是 TabControl 约定的定义方式:

    AddElementConvention<TabControl>(TabControl.ItemsSourceProperty, "ItemsSource", "SelectionChanged")
    .ApplyBinding = (viewModelType, path, property, element, convention) => {
        if(!SetBinding(viewModelType, path, property, element, convention))
            return;
    
        var tabControl = (TabControl)element;
        if(tabControl.ContentTemplate == null && tabControl.ContentTemplateSelector == null && property.PropertyType.IsGenericType) {
            var itemType = property.PropertyType.GetGenericArguments().First();
            if(!itemType.IsValueType && !typeof(string).IsAssignableFrom(itemType))
                tabControl.ContentTemplate = DefaultItemTemplate;
        }
    
        ConfigureSelectedItem(element, Selector.SelectedItemProperty, viewModelType, path);
    
        if(string.IsNullOrEmpty(tabControl.DisplayMemberPath))
            ApplyHeaderTemplate(tabControl, TabControl.ItemTemplateProperty, viewModelType);
    };
    

    我认为您应该能够获取代码并进行一些小的修改,使其按照您的意愿行事。请注意,上述代码中调用的一些方法实际上存在于 ConventionManager 中,因此您需要修复它。您应该在引导程序的配置覆盖中添加您的约定。有关这方面的其他示例,请查看 WP7 模板的 Bootstrapper,它定义了 Pivot 和 Panarama 的自定义约定。

    【讨论】:

      【解决方案2】:

      Caliburn.Micro.Telerik 包含 Telerik 的 WPF 控件的约定,以及其他一些 Telerik+WPF 特定的东西,例如 IWindowManager 实现和两个带有示例的应用程序。

      您可以查看source codenuget package

      RadTabControl 的约定如下所示:

      ConventionManager.AddElementConvention<RadTabControl>(RadTabControl.ItemsSourceProperty,
                                                        "ItemsSource",
                                                        "SelectionChanged")
      .ApplyBinding = (viewModelType, path, property, element, convention) =>
      {
          if (!ConventionManager.SetBindingWithoutBindingOrValueOverwrite(viewModelType,
                                                                          path,
                                                                          property,
                                                                          element,
                                                                          convention,
                                                                          RadTabControl.ItemsSourceProperty))
              return false;
      
          var tabControl = (RadTabControl) element;
          if (tabControl.ContentTemplate == null
              && tabControl.ContentTemplateSelector == null
              && property.PropertyType.IsGenericType)
          {
              var itemType = property.PropertyType.GetGenericArguments().First();
              if (!itemType.IsValueType && !typeof (string).IsAssignableFrom(itemType))
                  tabControl.ContentTemplate = ConventionManager.DefaultItemTemplate;
          }
          ConventionManager.ConfigureSelectedItem(element,
                                                  RadTabControl.SelectedItemProperty,
                                                  viewModelType,
                                                  path);
      
          if (string.IsNullOrEmpty(tabControl.DisplayMemberPath))
              ConventionManager.ApplyHeaderTemplate(tabControl,
                                                    RadTabControl.ItemTemplateProperty,
                                                    RadTabControl.ItemTemplateSelectorProperty,
                                                    viewModelType);
          return true;
      };
      

      希望这会有所帮助...

      【讨论】: