2011-06-01 86 views
9

當我嘗試將valueconverter從定義枚舉狀態結合到刷皈依的結果,我得到一個錯誤,在我的XAML設計:使用資源的綁定轉換器

沒有發現「OKStatus」資源。

該應用程序運行良好,但我無法在設計器中看到我的GUI。 我的資源是在運行時讀取的color.xaml文件中定義的。 所有的代碼都是相同的命名空間

我的XAML中:

的xmlns:配置= 「CLR的命名空間:App.MyNamespace」

<UserControl.Resources> 
    <ResourceDictionary> 
     <ResourceDictionary.MergedDictionaries> 
      <ResourceDictionary Source="c:\Skins\Colors.xaml" /> 
      <ResourceDictionary Source="c:\Skins\Common.xaml" />     
     </ResourceDictionary.MergedDictionaries> 
     <config:StatusConverter x:Key="StateConverter" /> 
     <config:BoolConverter x:Key="BoolConverter" /> 
     <config:BooleanConverter x:Key="BooleanConverter" /> 
    </ResourceDictionary> 
</UserControl.Resources> 

狀態

My conver之三:

[ValueConversion(typeof(bool), typeof(Brush))] 
public class BoolConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, 
     object parameter, CultureInfo culture) 
    { 
     bool state = (bool)value; 

     FrameworkElement FrameElem = new FrameworkElement(); 

     if (state == true) 
      return (FrameElem.FindResource("OKStatus") as Brush); 
     else 
      return (FrameElem.FindResource("ErrorStatus") as Brush); 
    } 

    public object ConvertBack(object value, Type targetType, 
     object parameter, CultureInfo culture) 
    { 
     return null; 
    } 
} 

在此代碼frameElem不會有我定義我猜資源的任何知識,所以我需要一種方式來獲得設計時訪問我的資源。 這可能嗎?

回答

-1

其實我落得這樣做(現在)是從FindResource改變TryFindResource,並把語句在try/catch塊。 這似乎工作到目前爲止。

try 
{ 
    if (state == true) 
     return (FrameElem.TryFindResource("OKStatus") as Brush); 
    else 
     return (FrameElem.TryFindResource("ErrorStatus") as Brush); 
} 

catch (ResourceReferenceKeyNotFoundException) 
{ 
    return new SolidColorBrush(Colors.LightGray); 
} 
+0

我個人與Joel的解決方案一起上面,因爲它似乎更少計算密集型。 TryFindResource會在我的應用程序中花費我不得不修改巨大數據網格中的項目顏色。 – Eternal21 2014-03-04 20:56:18

6

我認爲問題在於您正在嘗試從不在可視樹中的框架元素中找到資源。你可以嘗試以下方法嗎?

Application.Current.FindResource("OKStatus") as Brush; 
+0

讓我知道如果我是關閉基地。 – 2011-06-01 13:33:30

+1

如果資源位於應用程序級字典或系統資源中,這肯定會起作用。 – 2011-06-01 15:55:06

11

是的,這是可能的,你的猜測是正確的。資源查找從邏輯樹開始,創建新的FrameworkElement()不滿足此要求。它完全斷開連接。

你能做什麼(什麼你可能必須做的,如果N8的建議不工作),是你的手轉換器參考UserControlFrameworkElement調用FindResource()上。

N8的建議可能不會起作用的原因是Application.Current.FindResource()可能從應用程序級資源開始,然後轉到系統資源,但是您之後的資源位於UserControl的資源中。如果他們被放在App.xaml的資源中,它就會工作。但是,我認爲在設計時Application.Current可能是null

我能想到的最簡單的方法是在你的UserControl的構造:

public MyUserControl(){ 
    var boolconv = new BoolConverter(); 
    boolconv.FrameworkElement = this; 
    this.Resources.Add("BoolConverter", boolconv); 
    InitializeComponent(); 
} 

我敢肯定它InitializeComponent()先,而不是之後。

在XAML中執行此操作會更加複雜,因爲您可能必須將DependencyProperty添加到您的轉換器,以便您可以將UserControl綁定到它。我認爲那會太過分了。

另一種方法是把你的轉換器TrueBrushFalseBrush性能和XAML,這是我傾向於這樣做,我的轉換是含糊和籠統使用它們分配。 (注意:名稱略有不同。)

<config:BoolToBrushConverter x:Key="Bool2Brush" 
         TrueBrush="{StaticResource OKStatusBrush}" 
         FalseBrush="{StaticResource ErrorStatusBrush}" /> 
+1

謝謝喬爾,你的解決方案聽起來很乾淨。我對WPF世界很新。 – 2011-06-01 14:26:53

+0

這(使用屬性)絕對是一個更好的解決方案。 – CJBrew 2016-03-08 12:46:43

0

我也遇到過這個問題。我認爲調用Application.Current是從IValueConverter獲取資源的最佳方式,因爲它們並未在每個窗口或頁面或控件級別上定義。如上所述,這將需要資源至少是應用程序級別。

但是,由於Application.Current引用在設計器中設置爲null,所以此方法將始終打破設計器。你看起來已經做了什麼給設計師顯示一些東西,而你已經給了你正在運行的應用程序訪問轉換器中的資源。

對於你們所有人在這個問題上,你不需要執行lewi實施的Kludge;這隻有在你想要加載設計師表面的情況下。它不會影響您的應用程序,因爲Application.Current調用需要執行。

0

正如我從TechNet Wiki瞭解到的,必須使用MultiValue Converter和MultiValueBinding才能通過UserControl獲得正確的註冊轉換器和正確的FrameworkElement。

XAML示例:

<TextBlock x:Name="tb1" Margin="20"> 
<TextBlock.Text> 
    <MultiBinding Converter="{StaticResource MyConverter}"> 
    <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}"/> 
    <Binding Path="MyValue"/> 
    </MultiBinding> 
</TextBlock.Text> 
</TextBlock> 

然後轉換器聲明可以長相:

public class MyConverter : IMultiValueConverter 
{ 
    FrameworkElement myControl; 
    object theValue; 

    public object Convert(object[] values, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     myControl = values[0] as FrameworkElement; 
     theValue = values[1]; 

     return myControl.FindResource(">>resource u need<<"); 
     } 

     public object[] ConvertBack(object value, System.Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) 
    { 
    ..... 
    } 
} 

的詳細解釋是: https://social.technet.microsoft.com/wiki/contents/articles/12423.wpfhowto-pass-and-use-a-control-in-it-s-own-valueconverter-for-convertconvertback.aspx