2017-11-21 6 views
4

「再利用可能な」制御項目を作成して、動作属性を持たせたいとします。記載のとおりin this blogWPF対話コマンドは、コンバータのローカル静的リソースを参照します。

データバインディングの場合、データを変換する必要があります。問題は; StaticResourceというように、トップレベルの辞書(app)しか表示されず、動的リソースが機能しません(「依存プロパティーでのみ使用できます」)。

簡単な(ワーキング)XAML(ウィンドウ):

<Window x:Class="testit.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"   
     xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Rectangle x:Name="blah" Fill="Yellow" Stroke="Black" Width="100" Height="100"> 
      <i:Interaction.Triggers> 
       <i:EventTrigger EventName="MouseEnter" > 
        <i:InvokeCommandAction Command="{Binding MouseEnterCommand}"> 
         <i:InvokeCommandAction.CommandParameter> 
          <Binding Path="Name" 
            Converter="{StaticResource SelectionConverter}" 
            RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=Rectangle}" /> 
         </i:InvokeCommandAction.CommandParameter> 
        </i:InvokeCommandAction> 
       </i:EventTrigger> 
      </i:Interaction.Triggers> 
     </Rectangle> 
     <TextBlock x:Name="namefield" Text="{Binding Data}" HorizontalAlignment="Left" VerticalAlignment="Top"/> 
    </Grid> 
</Window> 

アプリ:

<Application x:Class="testit.App" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:local="clr-namespace:testit" 
      StartupUri="MainWindow.xaml"> 
    <Application.Resources> 
     <local:SelectionConverter x:Key="SelectionConverter" /> 
    </Application.Resources> 
</Application> 

そして最後のviewmodel:

using System; 
using System.ComponentModel; 
using System.Globalization; 
using System.Windows.Data; 

namespace testit 
{ 
    class ViewModel : INotifyPropertyChanged 
    { 
     private string _data; 
     private readonly DelegateCommand<string> _mouseEnterCommand = null; 

     public ViewModel() { 
      _data = "hello "; 
      _mouseEnterCommand = new DelegateCommand<string>(
       (s) => { 
        var a = s ?? "world "; 
        Data += s; 
        return; 
       }); 
     } 

     public DelegateCommand<string> MouseEnterCommand => _mouseEnterCommand; 

     public string Data { 
      get { return _data; } 
      set { 
       if (value == _data) return; 
       _data = value; 
       OnPropertyChanged("Data"); 
      } 
     } 


     public event PropertyChangedEventHandler PropertyChanged; 
     protected virtual void OnPropertyChanged(string propertyName) { 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    public class SelectionConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { 
      if (value == null) return ""; 
      char[] charArray = ((string)value).ToCharArray(); 
      Array.Reverse(charArray); 
      return new string(charArray); 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { 
      throw new NotImplementedException(); 
     } 
    } 
} 

今言ったように、この "作品" 。しかし、それは私が望むことをしません:それはトップレベルのリソース辞書を混乱させます。私はアプリからリソースを削除したいと思います。それをグリッドの下に置きます。 (または私が使っているどのパネルでも)。

<Grid.Resources> 
    <local:SelectionConverter x:Key="SelectionConverter" /> 
</Grid.Resources> 

編集:私は、ウィンドウ内のグリッドに線の上に追加した場合、次のエラーがコンパイルにスローされます(ラインと位置がConverter="{StaticResource SelectionConverter}"参照)

「'の値を提供します「System.Windows.StaticResourceExtension」で 例外がスローされました。行番号「13」および行位置「38」。内側の例外を除いて

は 'SelectionConverter' という名前のリソースを見つけることができません。リソース名は です。明確にするために

、これは修飾window.xamlある:

<Window x:Class="testit.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"   
     xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
     xmlns:local="clr-namespace:testit" 
     Title="MainWindow" Height="350" Width="525"> 
    <Grid> 
     <Rectangle x:Name="blah" Fill="Yellow" Stroke="Black" Width="100" Height="100"> 
      <i:Interaction.Triggers> 
       <i:EventTrigger EventName="MouseEnter" > 
        <i:InvokeCommandAction Command="{Binding MouseEnterCommand}"> 
         <i:InvokeCommandAction.CommandParameter> 
          <Binding Path="Name" 
            Converter="{StaticResource SelectionConverter}" 
            RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=Rectangle}" /> 
         </i:InvokeCommandAction.CommandParameter> 
        </i:InvokeCommandAction> 
       </i:EventTrigger> 
      </i:Interaction.Triggers> 
     </Rectangle> 
     <TextBlock x:Name="namefield" Text="{Binding Data}" HorizontalAlignment="Left" VerticalAlignment="Top"/> 
     <Grid.Resources> 
      <local:SelectionConverter x:Key="SelectionConverter" /> 
     </Grid.Resources> 
    </Grid> 
</Window> 
+0

グリッドが定義されているグリッドが使用されているコントロールの親である場合、私はそれがうまくいくはずだと思うでしょう。 –

+0

@EdPlunkett私は間違っていると思います。 – paul23

+1

グリッドの上部に 'Grid.Resources'を置いてみてください。 'StaticResource'は、解析プロセスの初期段階でリソースを解決します。 –

答えて

2

ProvideValueが呼び出されたときStaticResourceマークアップ拡張機能は、すぐにリソースを解決:

Lookup behavior for that resourceは荷重 - に類似しています現在のXAMLページのマークアップからをロードしたのリソースを検索するタイムルックアップ

Grid.ResourcesGridのコンテンツの後を定義されている場合Gridの内容が解析されるとき、これらのリソースは、「以前にロード」されていません。

だから、グリッドの最上部にリソースを置くので、そこに何かは、あなたがそれを使用する前に定義されています。あなたはDynamicResourceを使用することができたなら、あなたは大丈夫だろう

<Grid> 
    <Grid.Resources> 
     <local:SelectionConverter x:Key="SelectionConverter" /> 
    </Grid.Resources> 

    <Rectangle x:Name="blah" Fill="Yellow" Stroke="Black" Width="100" Height="100"> 
     <i:Interaction.Triggers> 
      <i:EventTrigger EventName="MouseEnter" > 
       <i:InvokeCommandAction Command="{Binding MouseEnterCommand}"> 
        <i:InvokeCommandAction.CommandParameter> 
         <Binding Path="Name" 
           Converter="{StaticResource SelectionConverter}" 
           RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=Rectangle}" /> 
        </i:InvokeCommandAction.CommandParameter> 
       </i:InvokeCommandAction> 
      </i:EventTrigger> 
     </i:Interaction.Triggers> 
    </Rectangle> 
    <TextBlock x:Name="namefield" Text="{Binding Data}" HorizontalAlignment="Left" VerticalAlignment="Top"/> 
</Grid> 

、もちろんのあなたが発見した理由のために、あなたはできません。

関連する問題