用户更改TabItem之前的事件

时间:2017-04-11 16:24:38

标签: wpf events

我有一个带TabControl的WPF应用程序和几个包含一个UserControl的TabItem。用户可以更改TabItem中包含的usercontrol中的条目,例如配置应用程序。

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

我有一个函数可以检查UserControl中是否有未保存的更改。 用户更改标签或关闭应用程序之前,我想让他选择保存,放弃或留在标签页上。

这可能吗?如果可以,怎么样?如果它需要一些除TabControl之外的其他控件/结构,那么它们也会起作用,因为我目前正处于规划阶段......

提前致谢,
弗兰克

4 个答案:

答案 0 :(得分:0)

您可以将交互性用于任何事件。这是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>

答案 1 :(得分:0)

如果要通过事件执行此操作,可以使用SelectionConhanged事件作为TabControl,使用Closing事件作为Window。像这样:

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
    }
}

答案 2 :(得分:0)

TabControl没有TabChanging事件。但是,您可以使用.Items.CurrentChanging事件。这仅适用于在TabControl

上设置IsSynchronizedWithCurrentItem="True"的情况

XAML **

  <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

数据完成后,允许移至另一个标签页。

答案 3 :(得分: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>

这里是处理&#34; Tabs&#34;的Mouse-Up-Event的处理程序。我创建了一个接口,每个用作控件的内容都必须实现。这允许用户控制通知&#34; Tab Control&#34;关于未保存的更改并采取适当的(用户选择)操作。 之后,它会加载新内容并更改&#34; Tab-Headers&#34;的外观。在我看来,对于标签更改的完全控制,这导致更多代码的数量是可以接受的。

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);
  }
}