トップ回答者
エラー発生時のControlTemplateでの表示に関して

質問
-
WPF+C#+Livetを使用している環境での質問になります。
プログラミングは初心者で、書籍、ネットで勉強しながら簡単な画面を構築していますが、以下の点で躓きました。
お手数ですが、どなたかに解決策等をご助言頂けると有難いです。
MainWindow.xamlは別ResourceDictionaryファイルからWindowのControlTemplateを取得しています。
MainWindow.xaml内のtextboxに別ResourceDictionaryに記載したエラー表示用のControlTemplateを利用してViewModel側でのエラー発生時にその内容を表示させようとしています。
ところが、WindowのControlTemplateを使用した画面ではエラーの表示が行われず、
WindowのControlTemplateを使用しないようにすると、エラーが表示されます。
最終形はWindowのControlTemplateもエラー表示用のControlTemplateも、両方を使用して画面を構築したいと考えていますが、どうすればよろしいでしょうか?
●Dictionary2.xaml:WindowのControlTemplate
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" xmlns:l="http://schemas.livet-mvvm.net/2011/wpf"> <Style x:Key="DefaultWindowStyle" TargetType="Window"> <Setter Property="Width" Value="1240"/> <Setter Property="Height" Value="800"/> <Setter Property="Title" Value="○●システム"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Window"> <Border Name="RootElement"> <Border.Background> <SolidColorBrush x:Name="BorderBrush" Color="White"/> </Border.Background> <Grid Margin="15"> <Grid.RowDefinitions> <!-- メインタイトル、ログインユーザ等 --> <RowDefinition Height="50"/> <RowDefinition Height="*" /> <RowDefinition Height="30"/> </Grid.RowDefinitions> <Grid Grid.Row="0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="250" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="150" /> <ColumnDefinition Width="105" /> </Grid.ColumnDefinitions> <Border Grid.Column="0"> <Border.Background> <SolidColorBrush Color="{DynamicResource {x:Static SystemColors.GradientInactiveCaptionColorKey}}"/> </Border.Background> </Border> <Border Grid.Column="1"> <Border.Background> <SolidColorBrush Color="{DynamicResource {x:Static SystemColors.HighlightColorKey}}"/> </Border.Background> <StackPanel Grid.Column="1" Margin="5" HorizontalAlignment="Center" x:Name="MainTitle"> <TextBlock Text="画面名" FontSize="25" FontWeight="Bold"> <TextBlock.Foreground> <SolidColorBrush Color="{DynamicResource {x:Static SystemColors.MenuColorKey}}"/> </TextBlock.Foreground> </TextBlock> </StackPanel> </Border> <Border Grid.Column="2" BorderThickness="1,1,0,1"> <Border.Background> <SolidColorBrush Color="{DynamicResource {x:Static SystemColors.GradientInactiveCaptionColorKey}}"/> </Border.Background> <StackPanel Grid.Column="2" Margin="5" HorizontalAlignment="Left" Orientation="Vertical"> </StackPanel> </Border> <Border Grid.Column="3" BorderThickness="0,1,1,1"> <Border.Background> <SolidColorBrush Color="{DynamicResource {x:Static SystemColors.GradientInactiveCaptionColorKey}}"/> </Border.Background> <StackPanel Grid.Column="2" Margin="0"> </StackPanel> </Border> </Grid> <ContentPresenter Grid.Row="1" Margin="0, 0"/> <Border Grid.Row="4" Background="Gray"> <StackPanel Grid.Row="4"> </StackPanel> </Border> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
●Dictionary3.xaml:エラーテンプレートのControlTemplate
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <ControlTemplate x:Key="ErrorTemplate"> <DockPanel> <ItemsControl DockPanel.Dock="Right" Margin="5,0" ItemsSource="{Binding ElementName=adornedElement, Path=AdornedElement.(Validation.Errors)}"> <ItemsControl.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding ErrorContent}" Foreground="Red"/> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> <Border BorderBrush="Red" BorderThickness="1" Width="{Binding ElementName=adornedElement, Path=ActualWidth}" Height="{Binding ElementName=adornedElement, Path=ActualHeight}"> <AdornedElementPlaceholder Name="adornedElement"/> </Border> </DockPanel> </ControlTemplate>
●MainWindow.xaml
<Window x:Class="LivetWPFApplication1.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" xmlns:l="http://schemas.livet-mvvm.net/2011/wpf" xmlns:v="clr-namespace:LivetWPFApplication1.Views" xmlns:vm="clr-namespace:LivetWPFApplication1.ViewModels"> <Window.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/Dictionary2.xaml"/> <ResourceDictionary Source="/Dictionary3.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Window.Resources> <Window.Style> <Binding Source="{StaticResource DefaultWindowStyle}"/> </Window.Style> <!--<Window.DataContext> <vm:MainWindowViewModel/> </Window.DataContext>--> <i:Interaction.Triggers> <i:EventTrigger EventName="ContentRendered"> <l:LivetCallMethodAction MethodTarget="{Binding}" MethodName="Initialize"/> </i:EventTrigger> <i:EventTrigger EventName="Closed"> <l:DataContextDisposeAction/> </i:EventTrigger> </i:Interaction.Triggers> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Border Grid.Row="0"> <StackPanel Grid.Row="0" Orientation="Vertical" VerticalAlignment="Center"> <TextBox Width="40" Text="{Binding txtItem,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged,ValidatesOnNotifyDataErrors=True}" Validation.ErrorTemplate="{StaticResource ErrorTemplate}"> </TextBox> <Button Content="dummy" Width="40"/> </StackPanel> </Border> </Grid> </Window>
※以下の3行をコメントアウトすると、エラー内容は正しく表示されます。
<Window.Style>
<Binding Source="{StaticResource DefaultWindowStyle}"/>
</Window.Style>
●MainWindow.xaml.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace LivetWPFApplication1.Views { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.DataContext = new LivetWPFApplication1.ViewModels.MainWindowViewModel(); } } }
●MainWindowViewModel.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using Livet; using Livet.Commands; using Livet.Messaging; using Livet.Messaging.IO; using Livet.EventListeners; using Livet.Messaging.Windows; using System.Globalization; using System.Runtime.CompilerServices; using System.Windows.Media; using LivetWPFApplication1.Models; namespace LivetWPFApplication1.ViewModels { public class MainWindowViewModel : ViewModel, INotifyDataErrorInfo { private Dictionary<string, string[]> Errors = new Dictionary<string, string[]>(); public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged; public void Initialize() { } #region MyProperty変更通知プロパティ private int _txtItem; public int txtItem { get { return _txtItem; } set { if (_txtItem == value) return; _txtItem = value; var _value = value.ToString(); string[] _ErrorInfo = Validate(_value); Errors["txtItem"] = _ErrorInfo; RaiseErrorsChanged("txtItem"); RaisePropertyChanged(); } } #endregion private List<string> _ErrorInfo = new List<string>(); public string[] Validate(object pValue) { var inputValue = pValue as string; if (inputValue != null) { _ErrorInfo.Add("値が入っていない"); } int parsedValue = 0; if (int.TryParse(inputValue, out parsedValue)) { _ErrorInfo.Add("値が数値ではない"); } if (parsedValue % 2 != 0) { _ErrorInfo.Add("値が偶数ではない"); } string[] _ErrorInfoResult = _ErrorInfo.ToArray(); return _ErrorInfoResult; } protected virtual void RaiseErrorsChanged([CallerMemberName]string propertyName = "") { var h = this.ErrorsChanged; if (h != null) { h(this, new DataErrorsChangedEventArgs(propertyName)); } } // エラーメッセージを取得する public System.Collections.IEnumerable GetErrors(string propertyName) { if (string.IsNullOrWhiteSpace(propertyName)) return null; if (!Errors.ContainsKey(propertyName)) return null; return Errors[propertyName]; } // エラーの有無 public bool HasErrors { get { return Errors.Values.Any(x => x != null); } } } }
- 編集済み akinari0321 2015年10月15日 14:51
回答
-
Adornerを表示するためのレイヤーが表示できなくなってます。
AdornerDecoratorをContentPresenterよりも外側に配置してみてください。
<ControlTemplate TargetType="Window"> <AdornerDecorator> <Border Name="RootElement"> <!-- 省略 --> </Border> </AdornerDecorator> </ControlTemplate>
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答の候補に設定 Tak1waMVP, Moderator 2015年10月16日 16:00
- 回答としてマーク 星 睦美 2015年10月30日 4:32
すべての返信
-
Adornerを表示するためのレイヤーが表示できなくなってます。
AdornerDecoratorをContentPresenterよりも外側に配置してみてください。
<ControlTemplate TargetType="Window"> <AdornerDecorator> <Border Name="RootElement"> <!-- 省略 --> </Border> </AdornerDecorator> </ControlTemplate>
個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)
- 回答の候補に設定 Tak1waMVP, Moderator 2015年10月16日 16:00
- 回答としてマーク 星 睦美 2015年10月30日 4:32