XAML如何制作文本块/文本框编辑切换?

时间:2012-12-24 00:46:45

标签: xaml winrt-xaml

我可能正在接近这一切,所以请告诉我你是否有其他建议。

我正在为Windows RT创建一个应用程序,它会向用户显示一堆文本块,例如字符统计信息。 用户将看到:

Str: 10
Con: 10
Dex: 10

等等。

我希望他们能够填充这些内容,然后根据结果计算出选择的视图值。

我的方法是点击顶部的“修改”按钮,然后在每个可编辑的文本块上切换一些文本框。

当尝试使用“Blend for Visual Studio”进行设置时,我似乎无法制作一个小于49x34的文本框(比我的文本块大得多)。

我打算找到一种方法在按钮点击时为每个文本块生成一个文本框(使用它的尺寸),但由于它们总是相同的,并且会有很多它们我试图制作它们静态混合。

我对XAML很陌生,我似乎无法找到人们设置这样的可编辑字段的好例子,那么我应该如何让一堆静态字段具有可编辑的文本框?

5 个答案:

答案 0 :(得分:6)

我会在XAML中创建TextBox和TextBlock叠加层,并将它们直接放在网格中,使用水平和垂直对齐“中心”以确保文本始终排成一行。我还会使用静态宽度来确保列排列良好。

从那里,您可以直接将Visibility绑定到某个布尔“IsEditing”属性,以确保一次只显示其中一个控件。

<StackPanel Orientation="Horizontal">
    <TextBlock Text="Str: " Width="40" VerticalAlignment="Center" />
    <Grid Width="40" VerticalAlignment="Center">
        <TextBlock Text="{Binding Strength}" 
            Visibility="{Binding IsEditing, Converter={StaticResource BooleanToInvisibilityConverter}}"
            VerticalAlignment="Center" 
            HorizontalAlignment="Center" />
        <TextBox Text="{Binding Strength}" 
            Visibility="{Binding IsEditing, Converter={StaticResource BooleanToVisibilityConverter}}"
            VerticalAlignment="Center" 
            HorizontalContentAlignment="Center" />
    </Grid>
</StackPanel>

在此过程中,您必须定义“BooleanToVisibility”和“BooleanToInvisiblity”转换器资源。我喜欢this implementation by Diedrik Krols。这很简单,可以选择反转。

答案 1 :(得分:4)

您可能希望为TextBox使用样式,该样式会根据“IsReadOnly”属性是否为true而更改。

当IsReadOnly为true时,您可以将BorderBrush和Background设置为Transparent,从而使其看起来像普通文本块。

通过这种方式,您不必覆盖TextBlocks和TextBoxes;只需单独使用TextBox控件,并在单击“编辑”按钮时切换“IsReadOnly”属性。

在您的资源中:

<Style x:Key="MyEditableField" TargetType={x:Type TextBox}>
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsReadOnly, RelativeSource={RelativeSource Self}}" Value="True">
            <Setter Property="BorderBrush" Value="Transparent" />
            <Setter Property="Background" Value="Transparent" />
        </DataTrigger>
    </Style.Triggers>
</Style>

这是您可编辑的字段之一:

<StackPanel Orientation="Horizontal">
    <TextBlock Text="Str: " />
    <TextBox Style="{StaticResource MyEditableField}"
             Text="{Binding Strength}"
             IsReadOnly="{Binding IsEditingDisabled}" />
</StackPanel>

答案 2 :(得分:4)

迟到的答案,但谁想要也可以创建一个自定义的可编辑文本框,其实很简单就是代码(显然你可以根据自己的需要修改它)

 public class EditableTextBox : TextBox
{
    public EditableTextBox()
    {
        this.BorderBrush = new SolidColorBrush(Colors.Black);
    }
    protected override void OnTapped(TappedRoutedEventArgs e)
    {
        this.IsReadOnly = false;
        SetEditingStyle();
        base.OnTapped(e);
    }

    protected override void OnDoubleTapped(DoubleTappedRoutedEventArgs e)
    {
        this.IsReadOnly = false;
        SetEditingStyle();
        base.OnDoubleTapped(e);
    }

    protected override void OnLostFocus(RoutedEventArgs e)
    {
        this.IsReadOnly = true;
        SetReadonlyStyle();
        base.OnLostFocus(e);
    }

    public void SetReadonlyStyle()
    {
        this.BorderBrush.Opacity = 0;
        this.Background.Opacity = 0;
    }

    public void SetEditingStyle()
    {
        this.BorderBrush.Opacity = 1;
        this.Background.Opacity = 1;
    }
}

样品:

enter image description here

enter image description here

教程:Full tutorial url

答案 3 :(得分:1)

使用属性在视图和viewmodel之间切换编辑模式是一种糟糕的设计方法,您应该使用事件和命令绑定来在视图和视图模型之间传达这种状态的更改。

这篇文章描述了符合MVVM的原则: http://www.codeproject.com/Articles/802385/A-WPF-MVVM-In-Place-Edit-TextBox-Control

请看一看并告诉我你的想法。

答案 4 :(得分:0)

这是基于BTownTKD的解决方案,但我真的更喜欢尽可能多的解决方案的WPF,这是一个修改,在我的情况下,我试图修改名称标签控件。

我的视图模型具有以下代码:

    private bool _isEditingName = false;

    public bool IsEditingName
    {
        get
        {
            return _isEditingName;
        }
        set
        {
            _isEditingName = value;
            OnPropertyChanged();
        }
    }

    public ICommand StartEditing
    {
        get
        {
            return new DelegateCommand(() =>
            {
                IsEditingName = true;
            });
        }
    }

    public ICommand EndEditing
    {
        get
        {
            return new DelegateCommand(() =>
            {
                IsEditingName = false;
            });
        }
    }

接下来是我的视图,其中包含选项卡的数据模板(而不仅仅是选项卡的内容):

<TabControl ItemsSource="{Binding Items}" SelectedItem="{Binding ActiveItem}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <Grid VerticalAlignment="Center">
                <TextBlock x:Name="TabName" Text="{Binding Name}" Visibility="{Binding IsEditingName, Converter={StaticResource InvertedBoolToVisConverter}}" VerticalAlignment="Center" HorizontalAlignment="Stretch" TextAlignment="Left">
                    <TextBlock.InputBindings>
                        <MouseBinding MouseAction="LeftDoubleClick" Command="{Binding StartEditing}" />
                    </TextBlock.InputBindings>
                </TextBlock>
                <TextBox Text="{Binding Name}" Visibility="{Binding IsEditingName, Converter={StaticResource BoolToVisConverter}}" VerticalAlignment="Center" HorizontalContentAlignment="Stretch" TextAlignment="Left" IsVisibleChanged="TextBox_IsVisibleChanged">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="LostFocus">
                            <i:InvokeCommandAction Command="{Binding EndEditing}" />
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                    <TextBox.InputBindings>
                        <KeyBinding  Key="Enter" Command="{Binding EndEditing}" />
                    </TextBox.InputBindings>
                </TextBox>
            </Grid>                 
        </DataTemplate>
    </TabControl.ItemTemplate>  
</TabControl>

最后但并非最不重要的是,我想要双击以使我进入编辑模式,并自动关注文本框并选择所有内容以立即输入。没有一个xaml解决方案像一个简单的代码一样干净,所以我最终决定将它添加到可见性改变处理程序的文本框中:

    private void TextBox_IsVisibleChanged(object sender, System.Windows.DependencyPropertyChangedEventArgs e)
    {
        var box = sender as TextBox;
        if (box != null)
        {
            if ((bool)e.NewValue)
            {
                box.Focus();
                box.SelectAll();
            }
        }
    }

在我发现的所有解决方案中,这是我最喜欢的。谢谢大家的帖子!!帮助我找到一个非常好的整体解决方案来解决我的问题!