我正在编写一个WPF输入对话框窗口,它将根据名为InputType的依赖项属性显示不同的Control。 我使用的语言是Visual COBOL .NET,但问题与语言无关,而与WPF本身无关,VB和C#程序员很容易理解该语言。 这是我的对话窗口的XAML代码
<Window x:Name="wndDialog"
x:Class="ClassLibraryNew.AGInputBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:lib="clr-namespace:ClassLibraryNew"
xmlns:ctrl="clr-namespace:ClassLibraryNew.Controls"
Width="400"
MinHeight="200"
WindowStyle="None"
WindowStartupLocation="CenterOwner"
ResizeMode="NoResize"
Background="#FFEEEEEE"
SizeToContent="Height"
MouseDown="OnMouseDown"
Loaded="OnLoaded">
<Window.CommandBindings>
<CommandBinding Command="{x:Static lib:DialogCommands.OkCommand}" CanExecute="OnCommandCanExecute" Executed="OnCommandExecuted"/>
<CommandBinding Command="{x:Static lib:DialogCommands.CancelCommand}" CanExecute="OnCommandCanExecute" Executed="OnCommandExecuted"/>
</Window.CommandBindings>
<Border Style="{StaticResource AGTWindowBorder}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<GroupBox Grid.Row="0" Header="{Binding Caption}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Text="{Binding Text}"
FontSize="{Binding Converter={StaticResource FontSizeConverter}, ConverterParameter='16'}"
VerticalAlignment="Center"
TextWrapping="Wrap"/>
<ContentControl Grid.Row="1" x:Name="contentControl" >
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Foreground="Red" Text="Errore: input type non valido. Contattare l'assistenza tecnica."/>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding InputType}" Value="Text">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<ctrl:TextField Text="{Binding Value, ElementName=wndDialog}"
ctrl:WatermarkService.Watermark="{Binding WatermarkText, ElementName=wndDialog}"
ctrl:WatermarkService.HideWhenFocused="False"
MaxLength="{Binding MaxLength, ElementName=wndDialog}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding InputType}" Value="Integer">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<ctrl:IntegerField Value="{Binding Value, ElementName=wndDialog}"
ZeroFill="{Binding ZeroFill, ElementName=wndDialog}"
MaxLength="{Binding MaxLength, ElementName=wndDialog}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding InputType}" Value="Decimal">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<ctrl:DecimalField Value="{Binding Value, ElementName=wndDialog}"
DecimalDigits="{Binding DecimalDigits, ElementName=wndDialog}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Grid>
</GroupBox>
<StackPanel Grid.Row="1"
Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="8">
<StackPanel.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource EuroButton}">
<Setter Property="Width" Value="80"/>
<Setter Property="Margin" Value="8,0,0,0"/>
</Style>
</StackPanel.Resources>
<Button IsDefault="True"
Command="{x:Static lib:DialogCommands.OkCommand}">
<AccessText Text="_Ok"/>
</Button>
<Button IsCancel="True"
Command="{x:Static lib:DialogCommands.CancelCommand}">
<AccessText Text="_Annulla"/>
</Button>
</StackPanel>
</Grid>
</Border>
我想要实现的是当InputType为Text时向用户显示'TextField'(自定义TextBox),当InputType为Integer时显示'IntegerField'等。 InputType的类型是枚举名称DialogInputType,它包含三个值(Text,Integer,Decimal)。 这工作正常,但我需要一种方法来将事件处理程序附加到ContentControl内的Field,当其内容已正确设置且不为null。 我期望DataTriggers在InputType更改时重新评估,而不是失败: (Visual COBOL .NET)
01 InputTypeProperty type DependencyProperty public static initialize only
value type DependencyProperty::Register(
"InputType",
type of DialogInputType,
type of AGInputBox,
new FrameworkPropertyMetadata(
type DialogInputType::Text,
new PropertyChangedCallback(method OnInputTypeChanged)
)
).
*> property definition omitted...
method-id OnInputTypeChanged private static.
procedure division using by value sender as type DependencyObject, by value e as type DependencyPropertyChangedEventArgs.
if sender not instance of type AGInputBox
goback
end-if
declare wnd as type AGInputBox = sender as type AGInputBox
if wnd::contentControl::Content instance of type FieldBase *> debugger arrives here
declare textField as type FieldBase
set textField = wnd::contentControl::Content as type FieldBase
attach method wnd::OnFieldTemplateApplied to textField::TemplateApplied
end-if
end method.
VS调试器显示ContentControl的内容为空,但是窗口正确可视化,并且可能稍后设置其内容... 在以下情况下它也是空的: - 窗口的加载事件 - 窗口的ContentRendered事件 我无法在DataTemplate控件中设置Loaded RoutedEventHandler,也不能使用Loaded =“OnFieldLoaded”或Style + EventSetter,因为它被禁止并且不会编译(即使编译器错误建议使用EventSetter:/)。
编辑:我尝试了l33t的解决方案但遗憾的是OnContentChanges永远不会被调用,即使内容设置正确也是如此。 我创建了这个类:
class-id ClassLibraryNew.Controls.NotifyingContentControl public
inherits type ContentControl.
01 ContentChanged type EventHandler event public.
method-id new public.
procedure division.
invoke super::new()
end method.
method-id OnContentChanged protected override.
procedure division using by value oldContent as object, by value newContent as object.
invoke super::OnContentChanged(oldContent, newContent) *> I put a debugger breakpoint here but it's not getting hit
invoke RaiseContentChanged()
end method.
method-id RaiseContentChanged private.
procedure division.
declare handler as type EventHandler = ContentChanged
declare e as type EventArgs = new EventArgs()
if handler not = null
invoke run handler(by value self, e)
end-if
end method.
end class.
答案 0 :(得分:1)
即使您设法确定内容的价值,也无法保证这是您在用户界面中看到的价值。
你可以试试这个:
public class ContentControlEx : ContentControl
{
protected override void OnContentChanged(object oldContent, object newContent)
{
// Do stuff...
base.OnContentChanged(oldContent, newContent);
}
}
然后使用ContentControlEx
代替常规的。{/ p>
答案 1 :(得分:1)
将Loaded
定义为资源并处理TextField
,IntegerField
和DecimalField
根元素的<ContentControl Grid.Row="1" x:Name="contentControl" >
<ContentControl.Resources>
<DataTemplate x:Key="tfTemplate">
<ctrl:TextField ... Loaded="LoadedHandler"/>
</DataTemplate>
<!-- + DataTemplates for IntegerField and DecimalField -->
</ContentControl.Resources>
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Foreground="Red" Text="Errore: input type non valido. Contattare l'assistenza tecnica."/>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding InputType}" Value="Text">
<Setter Property="ContentTemplate" Value="{StaticResource tfTemplate}" />
</DataTrigger>
<DataTrigger Binding="{Binding InputType}" Value="Integer">
<Setter Property="ContentTemplate" Value="{StaticResource ifTemplate}" />
</DataTrigger>
...
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
事件:
v-for