2010-01-04 20 views
20

我仍在努力將現有的WPF應用程序修改爲與MVVM方法「兼容」。我變得相當親近,但我不確定如何解決剩餘的幾個障礙之一。MVVM + WPF + Popup =無知

我有一個GUI元素(當前是一個按鈕,雖然它可能是一個標籤),當鼠標進入它時,它會觸發MouseEnter事件,並在代碼隱藏中創建一個彈出窗口。彈出窗口由一個簡單的帶有幾個按鈕的堆疊面板佈局組成。除了將Tag屬性更改爲執行簡單(俗氣)的命令參數外,當前每個按鈕的Click事件都被分配給相同的事件處理程序。我正在用MVVM的「正確」方式來做這件事,因爲我現在這樣做的方式非常難看。

爲了解決這個問題,我認爲這是我應該介紹的方向,但是希望能爲我提供任何額外的輸入。 :)

  1. 在XAML中創建彈出窗口。由於我的Popup內容是靜態的,我應該可以在XAML中完全創建Popup。另外,每個按鈕都將綁定到相同的ICommand派生類。例如

    <Popup x:Key="MyPopup" StaysOpen="False" Placement="Right"> 
        <Border Background="White" BorderBrush="Black" Padding="5" BorderThickness="2" CornerRadius="5"> 
         <StackPanel Orientation="Vertical"> 
          <Button Command="{Binding MyCommand}" CommandParameter="5">5</Button> 
          <Button Command="{Binding MyCommand}" CommandParameter="10">10</Button> 
          <Button Command="{Binding MyCommand}" CommandParameter="15">15</Button> 
          <Button Command="{Binding MyCommand}" CommandParameter="20">20</Button> 
         </StackPanel> 
        </Border> 
    </Popup> 
    
  2. 通過觸發器使彈出窗口彈出,例如,

         <Button.Triggers> 
              <Trigger Property="Button.IsMouseOver" Value="True"> 
               <Setter TargetName="MyPopup" Property="IsOpen" Value="True" /> 
              </Trigger> 
             </Button.Triggers> 
    

認爲#1是好的,但我與#2掙扎。這是解決問題的正確方法嗎?如果是這樣,將Popup的IsOpen屬性設置爲True的正確XAML語法是什麼?我找不到這方面的例子。

如果我的整個想法有缺陷,我很想聽聽我的其他選擇。謝謝!

+0

我沒有看到你的#2有什麼問題,也許你可以提供更多關於你認爲是錯誤的細節。 – 2010-01-04 07:08:49

+0

我得到錯誤「'IsOpen'成員無效,因爲它沒有合格的類型名稱。」 – Dave 2010-01-04 07:12:16

+0

我也試過Popup.IsOpen並得到了同樣的錯誤。 – Dave 2010-01-04 07:20:13

回答

17

以下是我將要做的事情,首先我將我的可重用部分分爲資源,並在XAML中使用ContentControls進行引用。這適用於Popup以及Button。不過,我不希望自己限制在只有一個按鈕,所以我會用一個ContentControl以及爲:

的彈出模板:

<ControlTemplate x:Key="PopupTemplate"> 
    <Border 
       Background="White" 
       BorderBrush="Black" 
       Padding="5" 
       BorderThickness="2" 
       CornerRadius="5"> 
     <StackPanel Orientation="Vertical"> 
      <Button Command="{Binding MyCommand}" 
          CommandParameter="5">5</Button> 
      <Button Command="{Binding MyCommand}" 
          CommandParameter="10">10</Button> 
      <Button Command="{Binding MyCommand}" 
          CommandParameter="15">15</Button> 
      <Button Command="{Binding MyCommand}" 
          CommandParameter="20">20</Button> 
     </StackPanel> 
    </Border> 
</ControlTemplate> 

ContentControl模板:

<ControlTemplate x:Key="MyControlTemplate" TargetType="ContentControl"> 
    <Grid Name="MyControl"> 
     <ContentPresenter Content="{TemplateBinding Content}"/> 
     <Popup Name="MyPopup" StaysOpen="True" Placement="Bottom"> 
      <ContentControl Template="{StaticResource PopupTemplate}"/> 
     </Popup> 
    </Grid> 
    <ControlTemplate.Triggers> 
     <Trigger SourceName="MyControl" 
       Property="UIElement.IsMouseOver" 
       Value="True"> 
      <Setter TargetName="MyPopup" 
        Property="Popup.IsOpen" 
        Value="True"/> 
     </Trigger> 
    </ControlTemplate.Triggers> 
</ControlTemplate> 

現在在主窗口的XAML,我會創建以下文件:

<ContentControl Template="{StaticResource MyControlTemplate}"> 
    <Button Content="Test"/> 
</ContentControl> 

如果您有任何問題,我會很樂意回答。

+1

感謝您的幫助!這聽起來像是一個很好的方向,我會讓你知道它是怎麼回事! – Dave 2010-01-04 13:44:44

+0

它幾乎工作!我現在唯一的問題是,當我在GUI中的其他地方單擊時,Popup消失(這是我想要的),但是當我再次將鼠標懸停在ContentControl上時,Popup不再出現。我是否必須在另一個觸發器中將IsOpen明確設置爲False?理想情況下,如果我點擊某個不是Popup或ContentControl(即某種複合/多重觸發器)的地方,我會讓Popup消失。 – Dave 2010-01-04 15:13:15

+0

我認爲這個問題可能是你將IsOpen明確設置爲false,從而忽略觸發器。你是否在代碼隱藏方面做到這一點?也許在彈出按鈕中的命令綁定處理程序?如果是這樣,你需要清除它的價值來重新啓用觸發器......這可能會很棘手。 – 2010-01-04 15:19:24