XAML如何进行文本块/文本框编辑切换?
我可能完全错了,所以如果你有其他建议,请告诉我 我正在为windows RT制作一个应用程序,它将向用户显示一组文本块,例如字符统计。 用户将看到: Str: 10 Con: 10 Dex: 10 Str:10 反对:10 指数:10 等等 我希望他们能够填写这些内容,然后根据结果计算选择视图值 我的想法是单击顶部的“编辑”按钮,在每个可编辑文本块上切换一些文本框 当尝试使用“Blend for Visual Studio”进行设置时,我似乎无法创建一个小于49x34的文本框(比我的文本块大得多) 我想找到一种方法,在点击按钮时为每个文本块(使用其尺寸)生成一个文本框,但由于它们总是相同的,而且会有很多,所以我试图通过blend使它们保持静态XAML如何进行文本块/文本框编辑切换?,xaml,winrt-xaml,Xaml,Winrt Xaml,我可能完全错了,所以如果你有其他建议,请告诉我 我正在为windows RT制作一个应用程序,它将向用户显示一组文本块,例如字符统计。 用户将看到: Str: 10 Con: 10 Dex: 10 Str:10 反对:10 指数:10 等等 我希望他们能够填写这些内容,然后根据结果计算选择视图值 我的想法是单击顶部的“编辑”按钮,在每个可编辑文本块上切换一些文本框 当尝试使用“Blend for Visual Studio”进行设置时,我似乎无法创建一个小于49x34的文本框(比我的文本块大得多
我对XAML非常陌生,我似乎找不到一个很好的例子来说明人们如何设置这样的可编辑字段,那么我应该如何使一组静态字段具有可编辑的文本框呢?您可能希望为文本框使用一种样式,它的变化取决于“IsReadOnly”属性是否为真 当IsReadOnly为true时,可以将边界笔刷和背景设置为透明,从而使其看起来像普通的文本块 这样,您就不必覆盖文本块和文本框;只需单独使用文本框控件,并在单击编辑按钮时切换“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>
我将在XAML中创建TextBox和TextBlock重叠,并将它们直接放置在网格中,使用水平和垂直对齐到“中心”,以确保文本始终完全对齐。我还将使用静态宽度,以确保列排列良好 从那里,您可以直接将可见性绑定到某个布尔“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”和“BooleanToVisibility”转换器资源。我喜欢。使用属性在视图和viewmodel之间切换编辑模式是一种糟糕的设计方法。您应该使用事件和命令绑定在视图和viewmodel之间传递类似这样的状态更改 以下是一篇文章,以符合MVVM的方式描述了该原则:
请看一看并告诉我你的想法。迟来的回答,但谁想要也可以创建一个自定义的可编辑文本框,其实很简单,这是代码(显然你可以根据自己的需要修改它) 样本:
教程:这是基于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;
});
}
}
接下来是我的视图,其中包含选项卡的数据模板(不是内容,只是选项卡):
在我找到的所有解决方案中,这是我最喜欢的。谢谢大家的帖子!!帮助我找到了一个很好的整体解决方案 因此,如果我理解正确,数据触发器意味着如果我将其设置为只读,则BorderBrush和Background将触发并关闭?我似乎在TargetType={x:Type TextBox}上遇到错误,它不喜欢将其作为有效名称。Datatrigger似乎也会抛出错误。我根本上误解了它的工作原理,或者我需要包括一些库吗?(今天早上在网上搜索没有显示太多)哦,天哪,进一步调查发现,Windows8XAML不再支持Style.Triggers。看起来您现在应该使用VisualStateManager了。这个答案需要更多的研究,因为结合使用VisualStateManager+Attached行为进行手动转换听起来有点过分了。我可能会发布一个全新的答案来帮助你以前的方法。谢谢!我在绞尽脑汁想弄明白为什么我的winRT项目不喜欢它。教程和文档似乎比XNA缺少很多,所以我(作为一名教程学习者)日子不好过。我很快就会考虑你的新答案:)第二个答案有用吗?这看起来正是我需要的。我只需要设置一下。谢谢请注意,我只是在我的项目中设置了它,当我尝试添加类似“”的内容时,在app.xaml中出现了“BooleantVisibilityConverter在windows应用程序项目中不受支持”语法错误。为什么这个xaml如此不同?似乎应该有一个简单的方法来实现这一点。我在回答的最后提到:您必须实现一个IValueConverter。下面是一个示例实现的链接,我实现了第一位(他在mvvm名称空间中,但我把它放在我自己的名称空间中)。不过,感谢您指出这一点,因为这让我回头看看,并意识到我忘记输入告知XAML名称空间存在的位!回到黑客攻击:)我不确定这里的礼仪,所以如果这个回答不应该是评论,请告诉我。在将'xmlns:Pathfinder=“using:MyNameSpace”'添加到我的App.xaml文件中之后,仍然会出现错误。我想我误解了如何将它添加到App.xaml文件中。在移出(已声明的)“”标记时,会出现不同的错误。无论我把它放在哪里,我总是会得到错误“BooleantVisibilityConverter在名称空间'using:MyNameSpace'中不存在”我想我可能只是从根本上误解了一些东西。
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>
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();
}
}
}