我正在编写一个WPF程序,我试图通过一些可重复的方法(如样式或模板)找出一种在TextBox中格式化数据的方法.我有很多TextBoxes(确切地说是95),每一个都绑定到自己的数值数据,每个数据都可以定义自己的分辨率.例如,如果数据为99.123,分辨率为2,则应显示99.12.同样,数据值99和分辨率3应显示为99.000(而不是99).有没有办法做到这一点?
编辑: 我应该澄清一下,我正在处理的当前屏幕上有95个TextBox,但我希望程序中各个屏幕的每个TextBox都能显示正确的小数位数.现在我考虑一下,其中一些是TextBoxes(就像我现在正在处理的屏幕),有些是DataGrids或ListViews,但是如果我能弄清楚如何使它适用于TextBoxes我敢肯定我可以想象它也用于其他控件.
在这种情况下,没有太多的代码可以共享,但我会尝试使其更清晰:
我有一个View Model,它包含以下属性(vb.net):
Public ReadOnly Property Resolution As Integer
Get
Return _signal.DisplayResolution
End Get
End Property
Public ReadOnly Property Value As Single
Get
Return Math.Round(_signal.DisplayValue, Resolution)
End Get
End Property
Run Code Online (Sandbox Code Playgroud)
在XAML中我有:
<UserControl.Resources>
<vm:SignalViewModel x:Key="Signal" SignalPath="SomeSignal"/>
</UserControl.Resources>
<TextBox Grid.Column="3" IsEnabled="False" Text="{Binding Path=Value, Source={StaticResource Signal}, Mode=OneWay}" />
Run Code Online (Sandbox Code Playgroud)
EDIT2(我的解决方案): 事实证明,在离开电脑一段时间之后,我回来找到一个简单的答案,盯着我的脸.格式化视图模型中的数据!
Public ReadOnly Property Value As String
Get
Return (Strings.FormatNumber(Math.Round(_signal.DisplayValue, _signal.DisplayResolution), _signal.DisplayResolution))
End Get
End Property
Run Code Online (Sandbox Code Playgroud) 简单的问题:如何在WPF中的dataGridCell上设置填充?(一次一个或所有细胞,我不在乎)
我已尝试通过在DataGrid.CellStyle
属性上添加setter DataGridCell.Padding
以及以DataGridColumn.CellStyle
相同方式使用属性而无效来使用该属性.
我也尝试使用该DataGridColumn.ElementStyle
物业,没有更多的运气.
我有点卡在那里,有没有人设法在dataGridCell上应用填充?
注意:我会补充说不,我不能使用透明边框来执行此操作,因为我已经将边框属性用于其他内容.我也不能使用margin属性(看起来工作得足够令人惊讶),因为我使用了background属性,我不希望我的单元格之间有任何"空白"空间.
我已经开始把自己列为"WPF陷阱"的列表:让我烦恼的事情,我不得不写下来记住,因为我每次都为他们堕落......
现在,我很确定你们在某一时刻偶然发现了类似的情况,我希望你们分享一下你们在这个问题上的经验:
什么是让你一直得到你的东西?你觉得最烦人的那个?
(我有几个问题似乎没有解释,也许你的提交将解释它们)
以下是我的一些"人物"陷阱(随机呈现):
即使单击位于控件(例如标签)的"透明"背景上而不仅仅是内容(本例中为文本)上,也要触发MouseEvent,控件的背景必须设置为"画笔".透明"而不仅仅是"null"(标签的默认值)
WPF DataGridCell的DataContext是单元所属的RowView,而不是CellView
在ScrollViewer中,滚动条由滚动查看器本身管理(即设置属性,如ScrollBar.Value没有效果)
Key.F10
当您按下"F10",而不是你是不是开除Key.System
,你必须去看看e.SystemKey
,以获得Key.F10
......现在你开始了.
一切都在标题中:
我不止一次读过设置这样的样式:
<Style TargetType="TextBox">...</Style>
Run Code Online (Sandbox Code Playgroud)
大致相当于:
<Style x:Key="{x:Type TextBox}" TargetType="TextBox">...</Style>
Run Code Online (Sandbox Code Playgroud)
(最后一次评论另一个问题)
两者都应该将样式应用于应用程序中的所有textBox(如果它们当然放在应用程序的资源中)
但是我在我的应用程序中都试过了,只有第二个用x:Key定义了.
它对我来说非常合乎逻辑,因为第一个不知道在没有任何x:Key属性集的情况下应用的位置,但那么第一个语法的重点是什么?
编辑:我的应用程序中的代码示例工作正常:
<Style x:Key="{x:Type ComboBoxItem}" TargetType="{x:Type ComboBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
Run Code Online (Sandbox Code Playgroud)
和代码不:
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
</Style>
Run Code Online (Sandbox Code Playgroud)
我写这个是为了摆脱你操纵现有ComboBox的itemsSource时用comboBoxItems得到的绑定问题.第一个代码工作正常,但第二个代码没有.
通过将horizontalContentAlignment设置为Right,您可以轻松地看到这一点
编辑2:这段代码只是放在App.xaml的资源字典中.用TargetType ="ComboBoxItem"替换TargetType ="{x:Type ComboBoxItem}"没有任何区别
编辑3:我刚刚意识到我可能忘记了确切的重要事项(对不起):尽管样式是在xaml中定义的,但我实际上是在我的代码中将控件添加到布局中,因为它们是动态添加的.可能是麻烦所在......
自从我开始使用MS的控件模板示例作为构建自定义控件的基础以来,我一直在想这个.
以Label示例为例:http://msdn.microsoft.com/en-us/library/ms752327.aspx
为什么它的定义如下:
<Style x:Key="{x:Type Label}" TargetType="Label">
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Border>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource DisabledForegroundColor}" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)
而不是直接这样:
<ControlTemplate x:Key="{x:Type Label}" TargetType="Label">
<Border>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
RecognizesAccessKey="True" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource DisabledForegroundColor}" />
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers> …
Run Code Online (Sandbox Code Playgroud) 我的项目中有一个简单的textBox.
我做了这种风格(为了说明目的):
<Style x:Key="{x:Type TextBox}" TargetType="{x:Type TextBox}">
<Style.Setters>
<Setter Property="Background" Value="LightGray"/>
</Style.Setters>
</Style>
Run Code Online (Sandbox Code Playgroud)
然后在某一点上,我正在做:MyTextBox.Background = Brushes.Red
在我的代码隐藏中.
到那里,一切正常.
现在我希望能够恢复原始的背景颜色,但没有硬编码.
即:我知道我可以做MyTextBox.Background = Brushes.LightGray
,但我正在寻找一种通用的方式,使我能够恢复到原始风格的背景属性,而不知道它.
我尝试将其设置为null,但当然它给了我一个透明的背景,这不是我想要的.
这有可能吗?如果是的话,我怎样才能实现这一目标?
谢谢
我有一个继承TextBox
Class的类,调用它MyTextBox
我想重新定义Background
这个类的默认值.
所以我找了一种方法,找到了一个很好的选择:打电话 BackgroundProperty.OverrideMetadata()
麻烦的是:我可以把它放在哪里?
在App.OnStartup()
?丑陋而不实用,我希望它在我的Class的代码文件中.
在班级的构造者?我得到一个例外:
PropertyMetadata已经为"MyTextBox"类型注册.
(对我来说似乎很好,我理解为什么我完美地得到这个)
所以我再次看了一下C#中的静态构造函数(之前没有关于那个,遗憾的是)
所以这是我的代码:
public class MyTextBox : TextBox
{
static MyTextBox()
{
MyTextBox.BackgroundProperty.OverrideMetadata(typeof(MyTextBox), new FrameworkPropertyMetadata(App.Current.Resources["CustomBackgroundBrush"]));
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我很高兴这一点,但微软不是.也就是说,当我使用代码分析功能时,我得到这个:
因此我的问题是:我能做些什么呢?
任何提示欢迎,谢谢
编辑:我要补充一点,我不完全理解为什么我会收到此警告,因为我没有在静态构造函数中初始化任何说法,或者是我?
我有一个函数,它将控件作为参数,并根据控件的类型(例如:TextBox,ComboBox,RadioButton等...),它执行特定于类型的代码:
internal static void DoSomething(Control control)
{
if (control is Button)
{
// code for button
}
else if (control is CheckBox)
{
// code for CheckBox
}
else if (control is TextBox)
{
// code for TextBox
}
// etc.....
}
Run Code Online (Sandbox Code Playgroud)
我想知道这是否是最好的方法.
我知道其他一些方法可以做同样的事情(例如:使用GetType()
此类型的字符串表示来查找控件的类型),Microsoft的代码分析工具告诉我使用'as'代替'is'就像这样(因为它在性能方面更好):
internal static void DoSomething(Control control)
{
Button button = control as Button
if (button != null)
{
// code for button
}
else
{
CheckBox checkBox = control as CheckBox;
if (checkBox != null) …
Run Code Online (Sandbox Code Playgroud) 我有一个像这样的DataGrid(WPF 4):
<DataGrid Margin="0,0,0,5" VerticalAlignment="Top" Height="192"
BorderBrush="#aaa" Background="White"
HorizontalAlignment="Left"
ItemsSource="{Binding Namen, Mode=OneWay}"
ScrollViewer.VerticalScrollBarVisibility="Visible"
AutoGenerateColumns="False"
ColumnHeaderHeight="24"
SelectionChanged="DataGridAuslaendischeAlteNamen_SelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Width="*" Header="Namenseintrag" Binding="{Binding DisplayName, Mode=OneWay}" />
<DataGridTextColumn Width="75" Header="gültig von" Binding="{Binding GueltigAb, StringFormat=d, Mode=OneWay}" />
<DataGridTextColumn Width="75" Header="gültig bis" Binding="{Binding GueltigBis, StringFormat=d., Mode=OneWay}" />
<DataGridTemplateColumn Width="20" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Style="{DynamicResource CaratRemoveButton}"
Click="Button_Click" CommandParameter="{Binding}"
PreviewMouseDown="Button_PreviewMouseDown"
/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是,DataGridTemplateColumn
如果未选中其行,则该按钮不会触发click事件.所以我必须两次单击一个按钮,一次选择它的行然后再提高click事件.我读过有关复选框列的类似问题,但显然建议使用模板列.我测试使用按钮的PreviewMouseDown-Event,它有效,但不是我想要的,因为那时按钮不遵循其通常的grpahical点击行为.
我在这里错过了什么?无论是否选择了行,如何只需单击一次即可获得该单击事件?
我今天遇到了一个非常奇怪的问题:
当我将鼠标悬停在图像上方时,我会打开一个弹出菜单.弹出菜单位于图像的右侧.
此弹出菜单模板看起来像一个带有指向图像的小箭头的矩形
菜单包含可点击的元素,所以我需要能够将鼠标从图像移动到菜单而不在它之间关闭,这就是我感到困惑的地方:如果我将鼠标移到箭头尖端然后菜单,一切正常.如果我将鼠标移动到图像和菜单之间的透明空间(箭头上方或下方),菜单将消失.
这是菜单的模板:
<Popup AllowsTransparency="True" Name="c_popup" Width="300" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right">
<Grid Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Path Data="M 0 10 L 10 0 10 20 Z" Stroke="#252C37" Fill="#252C37" Margin="0,18,0,0" Grid.Column="0" />
<Grid Grid.Column="1" Background="#252C37">
<TextBlock Text="{Binding Name}" Margin="20,10,0,0" FontSize="18" Foreground="White" HorizontalAlignment="Stretch" VerticalAlignment="Top" TextWrapping="WrapWithOverflow" />
</Grid>
</Grid>
</Popup>
Run Code Online (Sandbox Code Playgroud)
你会注意到我特意把Background =" Transparent "而不是Null(我知道这对hitTesting有什么影响,请看这个问题)
但有趣的是:如果我把Background ="#01000000",它按预期工作.(我几乎得到了我想要的东西,因为这几乎是一个透明的背景)
但我还是想知道那里发生了什么......
我怀疑这与popupmenu这个事实有关.我假设WPF做了一些事情来删除弹出菜单中透明的任何表面上的hitTesting,无论是背景为空(预期)还是特别设置为透明(不是预期的).谁能证实这一点?