2011-02-03 3 views
0

WPF MVVM 응용 프로그램이 있습니다. 내 의견 중 하나는 각 설치에 대해 사용자 정의 할 수있는 사용자 정의 컨트롤이 있습니다. 이것은 기본적으로 뷰 모델에 묶인 레이블 등을 가진 고객 설치의 스케치입니다.WPF 응용 프로그램 확장

이제 내 사용자 컨트롤이 각 사이트/설치마다 다릅니다. 한 가지 방법은 xaml 판독기를 사용하여 파일/데이터베이스 런타임에서 xaml을로드하는 것입니다. 이것은 작동하지만 내 viewmodel은 제네릭이므로 속성 대신 메서드에 바인딩해야하고 objectdataprovider으로 xaml을로드 할 수 없습니다.

현재 사용자 정의 컨트롤을 플러그인으로 만들 수 있도록 MEF를 사용할 수 있는지 확인하려고합니다. 내가 MEF

  • 어떻게 (내 WPF 응용 프로그램에서) 나의 부모보기 부하에 대한 계약을 수출 뷰/뷰 모델과 사용자 컨트롤을 정의 할 수있는 방법을

    1. 을 : 그래서 지금 찾고 있어요 것은 이것이다 가져온 사용자 컨트롤

    어떤 조언이나 평가가 도움이 되었습니까?

  • +0

    이 주석은 이해할 수 없습니다. "내 viewmodel은 일반 속성이므로 속성 대신 메서드에 바인딩해야합니다." 무슨 소리 야? –

    +0

    하나의보기가 xCounter에 바인딩되어 있다고 가정 해 보겠습니다. 다른보기는 xCounter와 yCounter에 바인딩되어 있습니다. 이것들은 x와 y를 매개 변수로 사용하여 getCounter()에 바인딩해야합니다. 따라서 새로운 바인딩으로 인해 뷰 모델을 변경할 필요가 없습니다. – Furnes

    +1

    차이점을 처리하는 것이 ViewModel의 책임이어야하는 것처럼 들리지만, 보기가 아니야. 아마도 샘플 Xaml 및 코드를 게시하여 시연 할 수 있습니까? –

    답변

    3

    MEF와 협력하여 Prism을 살펴 보시기 바랍니다. 모듈 (귀하의 경우에는 플러그인)과 지역 (동적으로 뷰를로드하는 메커니즘)이라는 개념이 있습니다.

    당신은 간단한 속성을 사용하여 뷰를 수출 할 수있을 것입니다 :

    <ContentControl Regions:RegionManager.RegionName="{x:Static Infrastructure:RegionNames.MyRegion}"/> 
    
    0

    하나 :

    [ViewExport(RegionName = RegionNames.MyRegion)] 
    public partial class MyView : UserControl { 
        public MyView() { 
         this.InitializeComponent(); 
        } 
    
        [Import] 
        public MyViewModel ViewModel { 
         set { DataContext = value; } 
        } 
    } 
    
    [Export] 
    public class MyViewModel : ViewModelBase 
    [ 
        ... 
    } 
    

    그리고 당신의 기본 응용 프로그램 XAML에서이 같은 플러그인의 의견을 가져올 수있을 것입니다

    내가 고려할 사항은 각 설치에 대해 사용자 지정보기를 설치해야하는 디자인입니다. 대신보기를 더 일반적인 것으로 만들 것입니다. 이렇게하면 장기적으로 디자인이 더욱 간단 해집니다. 또한, 에 대해 각각 설치 기준으로 다른 유지 보수 작업을해야합니다.

    귀하의 설명에서 알기는 약간 어렵지만보기가 어떤 종류의 개체 (레이블이있는 그림 등)의 모음 인 것처럼 들립니다. 그러므로 나는 그것을 이와 같이 취급 할 것이다.

    여러분의 뷰가 보여줄 수있는 모든 객체를 설명하는 기본 추상 클래스를 만들 것입니다. 필자는 더 많은 정보가 없으므로이 용어를 더 나은 용어가 부족한 "DrawingObject"라고 부릅니다. 이 클래스는 뷰의 모든 객체에 공통된 모든 정보를 보유합니다. ObservableItem은 INotifyPropertyChanged를 구현하는 클래스이며 SetProperty는 해당 기본 클래스의 값을 설정하고 PropertyChanged를 발생시킵니다.

    abstract class DrawingObject : ObservableItem 
    { 
        Point mPosition; 
        public Point Position 
        { 
         get { return mPosition; } 
         set { SetProperty("Position", ref mPosition, value); } 
        } 
    
        String mLabelText; 
        public String LabelText 
        { 
         get { return mLabelText; } 
         set { SetProperty("LabelText", ref mLabelText, value); } 
        } 
    } 
    

    그런 다음, 그 기본 클래스에서 더 많은 사용자 정의 객체를 파생 :

    class Counter : DrawingObject 
    { 
        public Counter() : base() 
        { 
        } 
    } 
    

    귀하의 뷰 모델은 바로 기본 클래스를 사용하여,이 개체의 컬렉션을 가질 것이다. 당신은 아마 (데이터베이스 또는 플랫 파일, 즉, 또는 ...) 생성자에서 어딘가에서 개체를 얻을

    class ViewModel : ObservableItem 
    { 
    
        public ViewModel() : base() 
        { 
         // Call something to populate DrawingObjects property 
         PopulateDrawingObjects(); 
        } 
    
        ObservableCollection<DrawingObject> mDrawingObjects = 
         new ObservableCollection<DrawingObject>(); 
        public ObservableCollection<DrawingObject> DrawingObjects 
        { 
         get { return mDrawingObjects; } 
         private set { mDrawingObjects = value; } 
        } 
    } 
    

    그런 다음보기가이 컬렉션에 바인딩 할 것 때문에 세트는 개인이 될 수 있습니다 그것들을 적절히 그리시오 (저는 이것을 구현 자의 연습으로 남겨 둘 것입니다).

    내가 보여주지 않은 한 가지 확장 기능은 DrawingObject가 적절한 직렬화 기능을 구현해야한다는 것입니다.

    분명히 이것은 설계의 대략적인 스케치이며 몇 가지 오류가있을 수 있습니다 (필자는 머리에서 그랬습니다). 그러나 계속 진행하면 충분합니다.