2014-02-10 94 views
4

我對WPF很新,並且在這裏尋找一些指導。WPF/MVVM設計建議

我正在開發一個應用程序,用於爲我們的執行部門打印工單。

現在我有2個窗口:第一個是主屏幕,第二個是帶有GridView的窗口,它將保存要打印的工單。

第一頁上會有幾個按鈕。每個按鈕都會打開第二個窗口;但是,根據點擊哪個按鈕,傳遞到將加載數據的服務的參數將有所不同。

這樣做的最佳做法是什麼?

  • 是否有辦法在Button控件的某處定義這些參數,然後通過ICommand/RelayCommand傳遞它們?
  • 我應該創建一個UserControl/ServerControl來讓我構建這些附加屬性嗎?
  • 其他我還沒想過的東西?

編輯:
要給出一個粗略的例子(這是很過分簡化},說我有2套標準:OrderTypes:{拉什,今天,未來}和位置{倉庫1,倉庫2,Warehouse 3}

主窗口將有一個3x3的按鈕網格,每個組合一個,我希望能夠在單個按鈕「Expedite & Warehouse 1」上指定;然後傳遞這些參數回到單個方法,這將打開第二個窗口。

回答

0

之前詳述任何事情,我會建議你使用第三方庫MVVMLight,它有許多有用的功能,如Messenger,自己的RelayCommands等等

  1. 對於從按鈕傳遞參數給他們滅絕命令,如果你想傳遞一個參數而不管事件的類型如何,你可以使用Tag屬性,如果你想傳遞一個與某個Command(event)相關的參數,那麼CommandParameter就是你所需要的:

Tag:獲取或設置可用於存儲有關此元素的自定義信息的任意對象值。 (繼承自FrameworkElement。)

CommandParameter:

<Button Content="Parameterized Command" 
    Command="{Binding ParameterizedCommand}" CommandParameter={Binding SomeObject} /> 
  1. 我不認爲你的問題,你需要創建一個用戶控件,除非你有更復雜的情況下的水平。
  2. 您可以使用Messenger類將信息從ViewModel傳遞給另一個(這只是一個與MVVM模式無關的幫助器)。
  3. MVVMLight具有代碼模板,可幫助您輕鬆創建ViewModels。
  4. MVVMLight有許多有用的代碼片段,您會發現很有幫助。
  5. 要小心命令,因爲它們最初並不支持所有UIElements,它們僅適用於ButtonBase及其子項,它們僅用於替換Click事件,將Commands和CommandParameters與其他UIElements以及其他類型的事件一起使用應該使用一種EventToCommand行爲,MVVMLight已經爲您準備好了

希望我介紹了您可能需要的最重要的部分。

+0

- 1用於提示Tag而不是命令參數。 – Bas

+0

@BasBrekelmans嗯,我認爲我錯了,然後,我正在考慮另一種情況,我會更新它,thx的評論 – AymenDaoudi

1

如果您不想使用某個第三方庫,只需將參數通過點擊事件傳遞到其他窗口的構造函數中就沒有問題。如果您的數據由視圖模型表示,則您也可以傳遞該視圖模型而不是參數本身。

MVVM的一點不是「沒有代碼隱藏」。很多時候,你會最終沒有代碼隱藏,但試圖以這種方式開發應用程序會導致你陷入複雜的反模式,與簡單的點擊事件和「舊模式」相比,這往往是更多的工作和更多的代碼行。

將您的數據視爲數據,嘗試在可測試的視圖模型中完成所有工作,並且不要過於嚴格地遵循某種模式,否則最終會遇到難以理解的抽象。

0

最容易和直觀的方式(使用INotifyPropertyChanged更新UI,而不是DependencyProperty):

您創建將是一個性質的DataContextOrderViewModelMainWindowViewModel

​​

現在,無論您如何創建您的訂單視圖:

  • 您實例化OrderViewModelMainWindowViewModel(讓我們說,當一個按鈕被點擊)與所需的參數。
  • 您在XAML中綁定了訂單視圖的DataContextOrderViewModelInstance。您可能想要創建一個額外的變量,告訴您何時可見窗口。
3

假設你有MainWindow並且按鈕被放置在它裏面。

  1. 創建MainWindowViewModel並將其設置爲DataContext的主窗口。

  2. 對您的視圖模型的ICommand和綁定按鈕命令與此ICommand使切入點打開另一個窗口將是單。對於ICommand,您可以使用RelayCommandDelegateCommand,以最適合您的爲準。

  3. 現在,您需要打開窗口並根據按鈕類型點擊傳遞參數。我建議有Enum描繪動作需要執行的基礎上不同的按鈕

枚舉

public enum ActionType 
{ 
    Action1, 
    Action2, 
    Action3 and so on... 
} 

並結合來自按鈕這樣的:

<Button Command="{Binding CommandInstance}" 
     CommandParameter="{x:Type local:ActionType.Action1}"/> 

<Button Command="{Binding CommandInstance}" 
     CommandParameter="{x:Type local:ActionType.Action2}"/> 

,當地將命名空間,其中枚舉是申報。

而且在命令執行委託傳遞枚舉值到另一個窗口構造函數:

private void CommandMethod(ActionType action) 
{ 
    AnotherWindow anotherWindow = new AnotherWindow(action); 
    anotherWindow.Show(); 
} 

,並在構造函數中傳遞的動作,你可以查閱一下參數需要傳遞給服務負責加載數據。

此外,如果從ViewModel創建窗口似乎不正確,你可以有窗口的服務包裝負責顯示/關閉窗口的控件。


UPDATE

既然你想從視圖,以便保持對枚舉這將是繁瑣的傳遞多個參數。您可以使用IMultiValueConverter通過傳遞來自View的多個值。

讓我與小例子說明一下:

<Button Command="{Binding TestCommand}"> 
    <Button.Resources> 
     <sys:String x:Key="Rush">Rush</sys:String> 
     <sys:String x:Key="Warehouse">Warehouse</sys:String> 
    </Button.Resources> 
    <Button.CommandParameter> 
     <MultiBinding Converter="{StaticResource MultiValuesReturnConverter}"> 
      <Binding Source="{StaticResource Rush}"/> 
      <Binding Source="{StaticResource Warehouse}"/> 
     </MultiBinding> 
    </Button.CommandParameter> 
</Button> 

其中sys將在XAML是命名空間系統:

xmlns:sys="clr-namespace:System;assembly=mscorlib" 

所以,現在你在XAML自由地從XAML通過大量的對象你的命令參數。你所要做的就是在按鈕資源部分聲明資源並將其作爲綁定傳遞給轉換器。

轉換代碼以將其轉換成可以傳遞作爲單個參數對象命令參數列表:

public class MultiValuesReturnConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, 
          object parameter, CultureInfo culture) 
    { 
     return values.ToList<object>(); 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, 
           object parameter, CultureInfo culture) 
    { 
     throw new System.NotImplementedException(); 
    } 
} 

命令方法:

private void CommandMethod(object parameter) 
{ 
    // Now you have all the parameters here to take decision. 
    IList<object> values = parameter as List<object>; 

    AnotherWindow anotherWindow = new AnotherWindow(action); 
    anotherWindow.Show(); 
} 
+0

我真的很喜歡這種方式,因爲單一的入口點。有沒有一種方法可以在那裏指定多個參數,還是我被鎖定爲1? –

+0

您只需要從View中傳遞參數?如果可以根據ActionType推導出來,我會建議在ViewModel中創建。 –

+0

我發佈了一個快速編輯的例子,我試圖完成。擁有一個ActionType可能會很快變得笨拙;因爲我有很多潛在類型 –