使用数据模板(WPF)在ListBox中内联编辑TextBlock

Ko9*_*Ko9 9 c# wpf xaml listbox datatemplate

使用WPF,我有ListBox一个DataTemplate内部控件.相关的XAML代码如下所示:

<ListBox Name="_todoList" Grid.Row="1" BorderThickness="2"
     Drop="todoList_Drop" AllowDrop="True"
     HorizontalContentAlignment="Stretch"
     ScrollViewer.HorizontalScrollBarVisibility="Disabled"                 
     AlternationCount="2">
     <ListBox.ItemTemplate>
         <DataTemplate>
             <Grid Margin="4">
                 <Grid.ColumnDefinitions>
                     <ColumnDefinition Width="Auto" />
                     <ColumnDefinition Width="*" />
                 </Grid.ColumnDefinitions>
                 <CheckBox Grid.Column="0" Checked="CheckBox_Check" />
                 <TextBlock Name="descriptionBlock"
                            Grid.Column="1"
                            Text="{Binding Description}"
                            Cursor="Hand" FontSize="14"
                            ToolTip="{Binding Description}"
                            MouseDown="TextBlock_MouseDown" />                      
             </Grid>
         </DataTemplate>
     </ListBox.ItemTemplate>
</ListBox>
Run Code Online (Sandbox Code Playgroud)

我想要做的是TextBlock对(双)点击做出响应,将其变成一个TextBox.然后,用户可以编辑描述,然后按返回或更改焦点进行更改.

我尝试TextBox在与TextBlock相同的位置添加一个元素并使其可见Collapsed,但我不知道TextBox当用户点击一个元素时如何向右导航TextBlock.也就是说,我知道用户点击了一定的TextBlock,现在 TextBox我说明了什么?

任何帮助将非常感激,

-Ko9

Nat*_*ler 15

我在这些情况下所做的是使用XAML层次结构来确定要显示/隐藏的元素.有点像:

<Grid>
  <TextBlock MouseDown="txtblk_MouseDown" />
  <TextBox LostFocus="txtbox_LostFocus" Visibility="Collapsed" />
</Grid>
Run Code Online (Sandbox Code Playgroud)

用代码:

protected void txtblk_MouseDown(object sender, MouseButtonEventArgs e)
{
    TextBox txt = (TextBox)((Grid)((TextBlock)sender).Parent).Children[1];
    txt.Visibility = Visibility.Visible;
    ((TextBlock)sender).Visibility = Visibility.Collapsed;
}

protected void txtbox_LostFocus(object sender, RoutedEventArgs e)
{
    TextBlock tb = (TextBlock)((Grid)((TextBox)sender).Parent).Children[0];
    tb.Text = ((TextBox)sender).Text;
    tb.Visibility = Visibility.Visible;
    ((TextBox)sender).Visibility = Visibility.Collapsed;
}
Run Code Online (Sandbox Code Playgroud)

我总是把这样的东西转换成我要重用的东西UserControl,我可以添加额外的错误处理,并保证Grid只包含两个项目,它们的顺序永远不会改变.

编辑:此外,将其转换为UserControl允许您Text为每个实例创建一个属性,因此您可以命名每个实例并直接引用文本而无需通过((TextBox)myGrid.Children[1]).Text转换捕获当前值.这将使您的代码更加高效和干净.如果将其设置为UserControl,则还可以命名TextBlockTextBox元素,因此根本不需要转换.


You*_*jae 13

请参阅Nathan Wheeler的代码片段,以下代码是我昨天编写的完整UserControl源代码. 特别是,解决了绑定问题. Nathan的代码很容易理解,但需要一些帮助才能使用数据绑定文本.

ClickToEditTextboxControl.xaml.cs

public partial class ClickToEditTextboxControl : UserControl
{
    public ClickToEditTextboxControl()
    {
        InitializeComponent();
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(ClickToEditTextboxControl), new UIPropertyMetadata());

    private void textBoxName_LostFocus(object sender, RoutedEventArgs e)
    {
        var txtBlock = (TextBlock)((Grid)((TextBox)sender).Parent).Children[0];

        txtBlock.Visibility = Visibility.Visible;
        ((TextBox)sender).Visibility = Visibility.Collapsed;
    }

    private void textBlockName_MouseDown(object sender, MouseButtonEventArgs e)
    {
        var grid = ((Grid) ((TextBlock) sender).Parent);
        var tbx = (TextBox)grid.Children[1];
        ((TextBlock)sender).Visibility = Visibility.Collapsed;
        tbx.Visibility = Visibility.Visible;

        this.Dispatcher.BeginInvoke((Action)(() => Keyboard.Focus(tbx)), DispatcherPriority.Render);
    }

    private void TextBoxKeyDown(object sender, KeyEventArgs e)
    {
        if (e == null)
            return;

        if (e.Key == Key.Return)
        {
            textBoxName_LostFocus(sender, null);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ClickToEditTextboxControl.xaml

<UserControl x:Class="Template.ClickToEditTextboxControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         Name="root"
         d:DesignHeight="30" d:DesignWidth="100">
<Grid>
    <TextBlock Name="textBlockName" Text="{Binding ElementName=root, Path=Text}" VerticalAlignment="Center" MouseDown="textBlockName_MouseDown" />
    <TextBox Name="textBoxName" Text="{Binding ElementName=root, Path=Text, UpdateSourceTrigger=PropertyChanged}" Visibility="Collapsed" LostFocus="textBoxName_LostFocus" KeyDown ="TextBoxKeyDown"/>
</Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

最后,您可以在XAML中使用此控件,如下所示:

<Template1:ClickToEditTextboxControl Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" MinWidth="40" Height="23" />
Run Code Online (Sandbox Code Playgroud)

请注意,Mode = TwoWay,UpdateSourceTrigger = PropertyChanged已设置.它可以更改每种类型的绑定值.