【问题标题】:Change a TabItem's name by double clicking the name通过双击名称更改 TabItem 的名称
【发布时间】:2021-10-10 19:43:19
【问题描述】:

我有一个TabControl,我正在尝试允许用户更改选项卡名称...但仅在双击名称时。这样,用户可以单击不同的选项卡名称来简单地更改活动选项卡,还可以根据需要更改选项卡名称。

到目前为止我尝试过的是捕获MouseDoubleClickLostFocus 事件,然后仅在双击选项卡名称时将“Focusable”属性设置为true。此方法的问题是LostFocus 事件在双击后立即触发,可能是因为焦点被设置为 TabItem 的内容。

我的选项卡控件 XAML:

    <Mah:MetroAnimatedTabControl x:Name="ViewTabs" DataContext="{Binding MyTabsViewModel}" ItemsSource="{Binding}">
        <Mah:MetroAnimatedTabControl.ItemTemplate>
            <DataTemplate DataType="{x:Type viewModels:MyTabViewModel}">
                <TextBox x:Name="TabNameTextBox" 
                         Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                         MouseDoubleClick="TabNameTextBox_MouseDoubleClick"
                         LostFocus="TabNameTextBox_LostFocus"
                         Cursor ="Arrow"/>        
            </DataTemplate>
        </Mah:MetroAnimatedTabControl.ItemTemplate>
    </Mah:MetroAnimatedTabControl>

事件MouseDoubleClickLost Focus背后的代码:

    private void TabNameTextBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        var textBox = (TextBox)sender;
        textBox.Focusable = true;
        textBox.Focus();
        textBox.SelectAll();
    }

    private void TabNameTextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        var textBox = (TextBox)sender;
        textBox.Focusable = false;
    }

我发现了一个similar question,其中提问者无法触发Lost Focus 事件。在我的情况下,它在我预期之前就开始了。

【问题讨论】:

  • 我会尝试以 MVVM 方式执行此操作,基本上将属性添加到 viewModels:MyTabViewModel 类似于 IsRenaming,然后当您处理鼠标双击时更改 IsRenaming 的值,这将基本上隐藏一个标签并使用Mah:MetroAnimatedTabControl.ItemTemplate等中的绑定显示一个文本框

标签: c# wpf xaml tabcontrol tabitem


【解决方案1】:

我得到了以下内容以使用标准 WPF TabControl。我的猜测是它也应该适用于Mah:MetroAnimatedTabControl

MainWindow.xaml:

<TabControl ItemsSource="{Binding Items}">
    <TabControl.ItemTemplate>
        <DataTemplate DataType="{x:Type local:Item}">
            <Grid>
                <TextBox x:Name="textBox" Text="{Binding Name,UpdateSourceTrigger=PropertyChanged}" LostFocus="textBox_LostFocus" Visibility="Collapsed"/>
                <TextBlock x:Name="textBlock" Text="{Binding Name}" MouseDown="TextBlock_MouseDown"/>
            </Grid>
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate DataType="{x:Type local:Item}">
            <TextBlock Text="{Binding Contents}"/>
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

MainWindow.xaml.cs:

public partial class MainWindow : Window
{
    private ObservableCollection<Item> items;

    public MainWindow()
    {
        InitializeComponent();
        Items.Add(new Item() { Name = "Item 1" });
        Items.Add(new Item() { Name = "Item 2" });
        Items.Add(new Item() { Name = "Item 3" });
        this.DataContext = this;
    }

    public ObservableCollection<Item> Items
    {
        get
        {
            if (items == null)
                items = new ObservableCollection<Item>();
            return items;
        }
    }

    private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
    {
        if (e.ClickCount == 2 && e.ButtonState == MouseButtonState.Pressed)
        {
            var grid = (Grid)VisualTreeHelper.GetParent(sender as UIElement);
            (sender as UIElement).Visibility = Visibility.Collapsed;
            grid.Children[0].Visibility = Visibility.Visible;
            grid.Children[0].Focus();
            ((TextBox)grid.Children[0]).SelectAll();
            e.Handled = true;
        }
    }

    private void textBox_LostFocus(object sender, RoutedEventArgs e)
    {
        var grid = (Grid)VisualTreeHelper.GetParent(sender as UIElement);
        (sender as UIElement).Visibility = Visibility.Collapsed;
        grid.Children[1].Visibility = Visibility.Visible;
    }
}

Item.cs:

public class Item : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public Item()
    {
        this.PropertyChanged += OnItemPropertyChanged;
    }

    private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == nameof(Name))
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Contents)));
        }
    }

    private string name;

    public string Name { get => name; set { name = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name))); } }

    public string Contents { get => $"Contents of {Name}"; }


}

双击“Item 3”标题名称后的屏幕截图:

【讨论】:

    猜你喜欢
    • 2011-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-22
    相关资源
    最近更新 更多