2017-04-11 64 views
0

我有一個WPF應用程序與一個TabControl和幾個TabItems包含一個UserControl每個。用戶可以更改TabItem中包含的usercontrol中的條目,例如配置應用程序。用戶更改前的事件TabItem

<TabControl> 
    <TabItem Header="Configuration"> 
    <views:ConfigurationView x:Name="ConfigurationView_Object" /> 
    </TabItem> 
    <TabItem Header="Artist"> 
    ... 
    </TabItem> 
</TabControl> 

我有一個函數,檢查UserControl中是否有未保存的更改。 之前用戶更改選項卡或關閉應用程序,我想讓他選擇保存,放棄或留在選項卡上。

這是可能的,如果是的話,怎麼樣?如果它需要一些其他控件/結構比TabControl的,這也wouls工作,因爲我在規劃階段目前是...

由於提前,
弗蘭克

回答

0

您可以使用交互性,任何event.This是MVVM解決方案。

<TabControl> 
    <TabItem Header="Configuration"> 
    <views:ConfigurationView x:Name="ConfigurationView_Object" /> 
    <intr:Interaction.Triggers> 
     <intr:EventTrigger EventName="MouseUp"> 
       <intr:InvokeCommandAction Command="{Binding Yourcommand}" CommandParameter="YourCommandParameter"/> 
       </intr:EventTrigger> 
     </intr:Interaction.Triggers> 

+0

的xmlns:INTR = 「CLR-名稱空間:System.Windows.Interactivity;裝配= System.Windows.Interactivity」 – leapold

+0

有趣的可能性。我不確定mouseup事件是否足以覆蓋改變標籤的所有可能的方式,然後我仍然需要防止標籤改變... – Aaginor

0

如果你想通過事件來做到這一點,你可以使用SelectionChanged事件對的TabControl和窗口Closing事件。事情是這樣的:

XAML:

<Window x:Class="Namespace.View" 
     ..... 
     Closing="Window_Closing"> 
...... 

C#:

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) 
{ 
    if (UnsavedChanges()) 
    { 
     //save changes    
    }   
} 

XAML:

<TabControl SelectionChanged="TabControl_SelectionChanged"> 
    <TabItem Header="Configuration"> 
    <views:ConfigurationView x:Name="ConfigurationView_Object" /> 
</TabItem> 
<TabItem Header="Artist"> 
    ... 
</TabItem> 
</TabControl> 

C#:

private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    if (UnsavedChanges()) 
    { 
     //save changes 
    } 
} 
+0

感謝您的回覆!重點是,我想讓用戶取消選中的選項卡上的更改。從我讀的關於它的Stackoverflow(http://stackoverflow.com/questions/30706758/how-to-cancel-tab-change-in-wpf-tabcontrol)這似乎是相當複雜的... – Aaginor

0

TabControl沒有TabChanging事件。但是,您可以使用.Items.CurrentChanging事件。這隻能如果您在TabControl的

XAML設置IsSynchronizedWithCurrentItem="True" **

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height='1*' /> 
     <RowDefinition Height='Auto' /> 
    </Grid.RowDefinitions> 
    <TabControl x:Name='MainTab' 
       IsSynchronizedWithCurrentItem='True' 
       Grid.Row='0'> 
     <TabItem x:Name='TabTickets' 
       Header='Tickets'> 

      <StackPanel Orientation='Horizontal' > 
      <TextBlock Text='Provide some text:' 
         Margin='10,0' /> 
      <TextBox x:Name='ExampleTextBox' 
        VerticalAlignment='Top' MinWidth='90' /> 
      </StackPanel> 

     </TabItem> 
     <TabItem x:Name='TabCalendar' 
       Header='Calendar' /> 
     <TabItem x:Name='TabAbout' 
       Header='About' /> 
    </TabControl> 

    <TextBlock x:Name='MessageTextBox' 
       Grid.Row='1' /> 

    </Grid> 

代碼

public TabChangingWindow() { 
     InitializeComponent(); 

     MainTab.Items.CurrentChanging += Items_CurrentChanging; 
    } 

    void Items_CurrentChanging(object sender, 
           System.ComponentModel.CurrentChangingEventArgs e) { 
     if (e.IsCancelable) 
     { 
     var fromElement = ((ICollectionView)sender).CurrentItem as FrameworkElement; 
     var toElement = MainTab.SelectedItem as FrameworkElement; 
     if (fromElement!= null && toElement!= null) 
     { 
      if (ExampleTextBox.Text.Length == 0) 
      { 
      e.Cancel = true; 
      MessageTextBox.Text = "Example Text cannot be blank."; 
      MainTab.SelectedItem = fromElement; 
      } 
      else 
      { 
      MessageTextBox.Text = 
      String.Format("Changing from {0} to {1}", fromElement.Name, toElement.Name); 
      } 

     } 

     } 

    } 

截圖

Prevent move to another tab

防止在數據不完整時移動到另一個選項卡。


Allow move to another tab

當數據是完整允許移動到另一個選項卡。

+0

感謝您的回覆!問題是,只要在更改期間沒有用戶交互,此解決方案就可以工作。 (請參閱http://stackoverflow.com/questions/30706758/how-to-cancel-tab-change-in-wpf-tabcontrol) 但我想問問用戶,他想做什麼(保存/ dicard /停留) – Aaginor

+0

您是否嘗試過這些代碼?用戶無法與用戶界面的任何其他部分進行交互,他們會被髮送回原始選項卡。如果這還不夠,可以使用消息框來提示用戶,並且可以在對話框上有按鈕來獲取用戶的信息。這是模式,用戶將無法與應用程序交互,直到消息框被解除。 –

+0

如何向用戶顯示對話框並獲取結果與您要求的不同。請參閱http://stackoverflow.com/questions/3830228/is-there-a-messagebox-equivalent-in-wpf –

0

我終於可以自己實現一個簡單的tabcontrol,因爲那樣我就可以控制一切。

<WrapPanel x:Name="WrapPanel_Main"> <!-- This is the TabControl --> 
    <Border x:Name="Border_Configuration" Margin="5,5,0,0" BorderThickness="4,4,4,0"> <!-- This is the first tab --> 
    <TextBlock x:Name="TextBlock_Configuration" Text="Configuration" Padding="5" MouseLeftButtonUp="TextBlock_Step_MouseLeftButtonUp"/> 
    </Border> 
    <Border Margin="5,5,0,0" BorderThickness="4,4,4,0"> <!-- This is the second tab --> 
    <TextBlock x:Name="TextBlock_Artists" Text="Artists" Padding="5" MouseLeftButtonUp="TextBlock_Step_MouseLeftButtonUp" /> 
    </Border> 
    <Border Margin="5,5,0,0" BorderThickness="4,4,4,0"> <!-- This is the third tab --> 
    <TextBlock x:Name="TextBlock_ReleaseGroups" Text="Release Groups" Padding="5" MouseLeftButtonUp="TextBlock_Step_MouseLeftButtonUp"/> 
    </Border> 
</WrapPanel> 

<Border x:Name="Border_Placeholder" Grid.Row="1" Margin="5,0,5,5"> <!-- placeholder for the content of each tab --> 
    <ContentControl x:Name="ContentControl_Placeholder" Grid.Row="1" Padding="5" /> 
</Border> 

這裏,是以 「標籤」 的鼠標向上事件的照顧處理。我創建了一個接口,每個用作該選項卡內容的用戶控件必須實現。這允許用戶控制通知「選項卡控制」關於未保存的更改並採取適當的(用戶選擇)動作。 之後,它加載新內容並更改「Tab-Headers」的外觀。在我看來,更多代碼的數量在完全控制選項卡更改方面是可以接受的。

private void TextBlock_Step_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
{ 
    ICancelUnloading currentElement = ContentControl_Placeholder.Content as ICancelUnloading; 
    if (currentElement != null) 
    { 
    if (currentElement.UnsavedChanges) 
    { 
     MessageBoxResult result = MessageBox.Show("Yes: Save, No: Discard, Cancel: Stay", "Unsaved Changes", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel); 
     if (result == MessageBoxResult.Cancel) 
     return; 
     if (result == MessageBoxResult.Yes) 
     currentElement.Save(); 
    } 
    } 

    TextBlock textBlock = sender as TextBlock; 
    if (textBlock != null) 
    { 
    switch (textBlock.Name) 
    { 
     case "TextBlock_Configuration": 
     ContentControl_Placeholder.Content = new ConfigurationView(); 
     break; 
     case "TextBlock_Artists": 
     ContentControl_Placeholder.Content = new ArtistsView(); 
     break; 
     case "TextBlock_ReleaseGroups": 
     ContentControl_Placeholder.Content = new ReleaseGroupsView(); 
     break; 
    } 

    ActivateTab(textBlock); 
    } 
}