2015-09-22 16 views
5

Ứng dụng của tôi có khoảng 15 UserControl khác nhau được tải đồng đều vào vùng nội dung khi chạy.Thêm trình kích hoạt cho mỗi UserControl

dự án của tôi là 100% MVVM tuân thủ, vì vậy tôi đã XAML sau chèn vào XAML của mỗi UserControl:

<UserControl 
    ... 
    xmlns:intr="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
> 

    <intr:Interaction.Triggers> 
     <intr:EventTrigger EventName="Loaded"> 
      <intr:InvokeCommandAction Command="{Binding ViewLoadedCommand}"/> 
     </intr:EventTrigger> 
    </intr:Interaction.Triggers> 

    <!-- Rest of UserControl content here --> 

</UserControl> 

Rõ ràng đây không phải là lý tưởng và cũng là một vi phạm DRY.

Cách tốt nhất để áp dụng XAML này cho tập hợp UserControls này là gì? (nhưng không phải mỗi UserControl, do đó, đơn giản <Style Type="UserControl" /> sẽ không phù hợp).

+0

Tại sao không tạo kiểu với khóa? –

+0

@Nikita Thực ra, tôi không biết cách tạo ra một kiểu đặt các thuộc tính đính kèm phức tạp và phức tạp như 'Tương tác.Trích ứng'. – Dai

+0

ViewLoadedCommand nằm ở đâu? Đây có phải là trong mô hình xem của bạn không? Bạn có chắc chắn muốn gọi lệnh này ** mỗi lần ** điều khiển người dùng được tải không? –

Trả lời

0

bạn có thể tạo Điều khiển người dùng "cơ sở tải" bằng Tương tác.Trích ứng và chỉ cần đặt một ContentPresenter vào đó nơi bạn ràng buộc nội dung thực.

<UserControl x:class="OneOfMyOtherControls"> 
    <MyBaseUserControl> 
    <!-- your UserControl Content--> 
    </MyBaseUserControl> 
</UserControl> 
4

Tôi sử dụng hành vi được triển khai dưới dạng thuộc tính đính kèm. Nó có hai lợi thế chính so với System.Windows.Interactivity:

  • nó có thể được xác định theo kiểu.
  • mã XAML ít hơn nhiều trong quan điểm

trong trường hợp của bạn, quan điểm có thể trông giống như:

<UserControl ... 
      my:AttachedCommands.LoadedCommand="{Binding ViewLoadedCommand}"> 

Trong giải pháp của tôi, tôi không sử dụng các lệnh, nhưng tôi gọi các phương thức trên viewmodel nếu viewmodel thực hiện IViewModelLifeCycle giao diện:

public interface IViewModelLifeCycle 
{ 
    void Activate(object extraData); 
    void Deactivate(); 
} 

Tất cả các quan điểm của tôi sử dụng phong cách này:

0.123.
<Style x:Key="ViewBaseStyle"> 
    <Setter Property="my:ViewModelLifeCycleBehavior.ActivateOnLoad" Value="True" /> 

và hành vi:

public static class ViewModelLifeCycleBehavior 
{ 
    public static readonly DependencyProperty ActivateOnLoadProperty = DependencyProperty.RegisterAttached("ActivateOnLoad", typeof (bool), typeof (ViewModelLifeCycleBehavior), 
     new PropertyMetadata(ActivateOnLoadPropertyChanged)); 

    public static void SetActivateOnLoad(FrameworkElement element, bool value) 
    { 
     element.SetValue(ActivateOnLoadProperty, value); 
    } 

    public static bool GetActivateOnLoad(FrameworkElement element) 
    { 
     return (bool)element.GetValue(ActivateOnLoadProperty); 
    } 


    private static void ActivateOnLoadPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) 
    { 
     if (DesignerProperties.GetIsInDesignMode(obj)) return; 
     var element = (FrameworkElement)obj; 

     element.Loaded -= ElementLoaded; 
     element.Unloaded -= ElementUnloaded; 

     if ((bool) args.NewValue == true) 
     { 
      element.Loaded += ElementLoaded; 
      element.Unloaded += ElementUnloaded; 
     } 
    } 



    static void ElementLoaded(object sender, RoutedEventArgs e) 
    { 
     var element = (FrameworkElement) sender; 
     var viewModel = (IViewModelLifeCycle) element.DataContext; 
     if (viewModel == null) 
     { 
      DependencyPropertyChangedEventHandler dataContextChanged = null; 
      dataContextChanged = (o, _e) => 
      { 
       ElementLoaded(sender, e); 
       element.DataContextChanged -= dataContextChanged; 
      }; 
      element.DataContextChanged += dataContextChanged; 
     } 
     else if (element.ActualHeight > 0 && element.ActualWidth > 0) //to avoid activating twice since loaded event is called twice on TabItems' subtrees 
     { 
      viewModel.Activate(null); 
     } 
    } 

    private static void ElementUnloaded(object sender, RoutedEventArgs e) 
    { 
     var element = (FrameworkElement)sender; 
     var viewModel = (IViewModelLifeCycle)element.DataContext; 
     viewModel.Deactivate(); 
    } 


} 

TIP: Tạo custom Item Template trong Visual Studio cho Xem và ViewModel của bạn. nó rất dễ dàng và tiết kiệm rất nhiều thời gian. Mẫu mục có thể chứa mã xaml với trình kích hoạt/hành vi, trỏ đến kiểu cơ sở của bạn, định nghĩa d:DataContext và lớp chế độ xem của bạn.

Các vấn đề liên quan