2014-03-31 136 views
0

我創建了兩個用戶控件,其中一個在Canvas上顯示了我的數據/視圖模型集合的2D笛卡爾映射。另一個是1列可滾動圖像庫,它爲每個數據模型顯示圖像。該(snippetized)地圖是基於:Wpf屬性綁定與命令

<ItemsControl 
     ItemsSource="{Binding Defects}" 
     ItemTemplateSelector="{StaticResource IconSelector}">    
     <!-- ItemsPanelTemplate --> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <Canvas x:Name="MapCanvas" Height="10000"/>      
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <!-- ItemContainerStyle --> 
     <ItemsControl.ItemContainerStyle> 
      <Style> 
       <Setter Property="Canvas.Top" Value="{Binding Y}" /> 
       <Setter Property="Canvas.Left" Value="{Binding X}" />      
      </Style>    
     </ItemsControl.ItemContainerStyle> 
</ItemsControl> 

的(再次,snippetized)圖片庫是基於:

<ScrollViewer Name="ScrollContainer" 
     Grid.Column="1" PanningMode="VerticalOnly" 
     VerticalScrollBarVisibility="Visible" 
     HorizontalScrollBarVisibility="Visible"     
     Background="White"> 
    <ItemsControl Name="ItemsContainer" ItemsSource="{Binding Defects}"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Border BorderThickness="5" BorderBrush="Gray" Margin="2"> 
        <Image Source="{Binding ImageUrl}" Margin="2"></Image> 
       </Border> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</ScrollViewer> 

現在我想一些同步增加這兩種觀點我數據。也就是說,當地圖上的其中一個圖標被點擊時,我希望圖庫滾動到相應的圖像。 我試圖添加一個依賴項屬性到兩個控件來指向選定的索引。這不是我想要的,但我想要一些額外的靈活性。有時我想用動畫來完成滾動,有時候我想要選擇的索引立即同步。 正因爲如此,我曾嘗試將自定義命令BringIntoView添加到視圖模型中。該命令使用布爾輸入來指定操作是否必須使用動畫執行。我可以將數據模板綁定到我的自定義命令,並且只要單擊地圖上的圖標,地圖控件就會正確調用自定義命令上的執行。

但是我被困在畫廊的一面,我怎樣才能將這個命令綁定到方法後面的一些代碼,或者可能是控件上的其他方法?命令綁定不起作用,因爲它不允許動態綁定到命令。下面提出了一個編譯時錯誤,因爲對的CommandBinding命令屬性不是依賴項屬性:

<UserControl.CommandBindings> 
    <CommandBinding Command="{Binding BringIntoView}" Executed="OnBringIntoViewExecuted"/> 
</UserControl.CommandBindings> 

我可以直接添加靜態命令與給定的那一個,但是這至少會配合視圖到viewmodel命令。那麼,如何實現這種級別的命令鏈接,同時保持與視圖的解耦?

換句話說,WPF依賴項屬性系統允許綁定兩個UI控件的兩個UI特定屬性。我怎樣才能達到相同的命令/事件?也就是說,來自用戶控件的UI事件/命令連接到另一個UI控件的方法/命令?

回答

0

我找到了解決這個設計問題的方法。與依賴項屬性發生的情況類似,自定義控件也可以公開自定義命令。由於控件直接暴露的命令(與視圖模型暴露的命令相反)是特定於UI的,所以最好使用RoutedUiCommand而不是自定義ICommand實現。 RoutedUiCommands可以作爲靜態屬性公開,就像DependencyProperty發生的一樣。就我而言,畫廊控制公開靜態BringIntoView命令,例如:

<UserControl.CommandBindings> 
    <CommandBinding Command="{x:static local:DefectGallery.BringIntoView}" Executed="OnBringIntoViewExecuted"/> 
</UserControl.CommandBindings> 

最後,一些其他:

public partial class DefectGallery { 
    // the control exposes the following commands: 
    public static readonly RoutedUiCommand BringIntoView = new RoutedUiCommand; 
    // the control exposes the following depdendency properties: 
    public static readonly DependencyProperty ScrollSpeedProperty = DependencyProperty.Register(...); 
    ... 
} 

該命令從DefectGallery控制的XAML文件綁定到代碼隱藏控件需要觸發BringIntoViewCommand。它可以例如一個WPF提供了一個按鈕的命令源。就我而言,我已經在地圖控件上實現了ICommandSource接口,以便允許指定一個自定義命令,只要單擊地圖上的圖標就會執行該命令。我現在可以從XAML使用地圖控制(上述的第一代碼段)是這樣的:

<MapControl 
    Command="{x:static local:DefectGallery.BringIntoView}" 
    CommandTarget="{Binding ElementName=defectGalleryInstance}" 
/> 

從而有效我「呼叫」只使用聲明性XAML從另一個控制的控制。

現在,這似乎是添加依賴屬性的基本模式,所以我只是感到驚訝,我還沒有找到這方面的指導。對我來說,控制暴露屬性和命令似乎很自然。我認爲這兩個是UI控件向其他UI組件的「接口」,而View模型綁定是應用程序層的接口。哦,WPF適用於不同的使用方法,您只需要找到適合您/您的應用程序的內容。