2010-08-20 67 views
1

我正在WPF中構建一個程序,該程序必須具有多語言支持,並且能夠在運行時切換語言。我的問題涉及本地化的圖像部分。將圖片本地圖片WPF

我已經構建了一個解決方案,它不能以我希望它能工作的方式工作,我希望能解決這些問題。下面發佈的代碼僅僅是我試圖實現的概念的一個演示。我的真實程序有很多圖片,所以我想避免將它們全部放入列表中,逐一更新它們。

我的想法是根據它們所屬的語言來命名圖像。 OriginalSource屬性(缺少更好的名稱)格式化爲「Koala。(lang).jpg」,英語和法語的兩個圖像分別稱爲「Koala.en-GB.jpg」和「Koala.fr-FR .JPG」。

我的問題是沒有在(1)處註釋的代碼,圖像將不會被分配一個「真正的」源(在Image類中)。 (1)處的代碼(這違反了我希望不使用所有圖像的枚舉)之後,在(2)點擊按鈕時,「真實」源不會被更新(012)。我的希望是(3)和(4)能夠解決這些問題,但顯然他們沒有。

幫助將不勝感激。 代碼如下:

MainWindow.xaml(不正確的)

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApplication1" 
     Title="MainWindow" Height="700" Width="525"> 
    <Window.Resources> 
     <local:LanguageCodeSetter x:Key="CodeSetter" LanguageCodeValue="en-GB" /> 
    </Window.Resources> 

    <StackPanel> 
     <local:LocalizedImage x:Name="imgKoala" LanguageCode="{Binding Source={StaticResource CodeSetter}, Path=LanguageCodeValue, Mode=OneWay}" OriginalSource="Koala.(lang).jpg" Height="300" Stretch="Uniform" /> 
     <local:LocalizedImage x:Name="imgPenguins" LanguageCode="{Binding Source={StaticResource CodeSetter}, Path=LanguageCodeValue, Mode=OneWay}" OriginalSource="Penguins.(lang).jpg" Height="300" Stretch="Uniform" /> 
     <Button Content="Don't click here!" Click="Button_Click" /> 
    </StackPanel> 
</Window> 

MainWindow.xaml.cs(不正確的)

using System; 
using System.ComponentModel; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media.Imaging; 

namespace WpfApplication1 
{ 
    public partial class MainWindow : Window 
    { 
     private string LanguageCodeResource 
     { 
      get 
      { 
       return ((LanguageCodeSetter)Resources["CodeSetter"]).LanguageCodeValue; 
      } 
      set 
      { 
       ((LanguageCodeSetter)Resources["CodeSetter"]).LanguageCodeValue = value; 
      } 
     } 

     public MainWindow() 
     { 
      InitializeComponent(); 

      //(1) 
      //imgKoala.OriginalSource = imgKoala.OriginalSource; 
      //imgPenguins.OriginalSource = imgPenguins.OriginalSource; 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      LanguageCodeResource = "fr-FR"; 

      //(2) 
      //imgKoala.LanguageCode = imgKoala.LanguageCode; 
      //imgPenguins.LanguageCode = imgPenguins.LanguageCode; 
     } 
    } 

    public class LocalizedImage : Image 
    { 
     public static readonly DependencyProperty LanguageCodeProperty = DependencyProperty.Register("LanguageCode", typeof(string), typeof(LocalizedImage)); 
     public static readonly DependencyProperty OriginalSourceProperty = DependencyProperty.Register("OriginalSource", typeof(string), typeof(LocalizedImage)); 

     public string LanguageCode 
     { 
      get 
      { 
       return (string)GetValue(LanguageCodeProperty); 
      } 
      set 
      { 
       SetValue(LanguageCodeProperty, value); 
       //(3) 
       SetValue(SourceProperty, new BitmapImage(new Uri(OriginalSource.Replace("(lang)", value), UriKind.RelativeOrAbsolute))); 
      } 
     } 

     public string OriginalSource 
     { 
      get 
      { 
       return (string)GetValue(OriginalSourceProperty); 
      } 
      set 
      { 
       SetValue(OriginalSourceProperty, value); 
       //(4) 
       SetValue(SourceProperty, new BitmapImage(new Uri(value.Replace("(lang)", LanguageCode), UriKind.RelativeOrAbsolute))); 
      } 
     } 
    } 

    public class LanguageCodeSetter : INotifyPropertyChanged 
    { 
     private string _languageCode; 

     public event PropertyChangedEventHandler PropertyChanged; 

     public string LanguageCodeValue 
     { 
      get 
      { 
       return _languageCode; 
      } 
      set 
      { 
       _languageCode = value; 
       NotifyPropertyChanged("LanguageCodeValue"); 
      } 
     } 

     private void NotifyPropertyChanged(string info) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(info)); 
      } 
     } 
    } 
} 

@NVM

  • 點混淆名稱。我更新了我的代碼。
  • 我使用INotifyPropertyChanged對象的原因是我希望一個變量的變化,即稱爲CodeSetter的資源傳播到LocalizedImage的所有實例。原因是我正在構建一個包含大量圖像的WPF應用程序,而且我不希望被迫將它們全部添加到代碼隱藏的列表中(因此忘記添加一些圖像並使未來重構應用程序更乏味)。點擊按鈕時,「LanguageCode」的值在LocalizedImage的所有實例中都會發生變化,因此傳播部分似乎可以工作。然而,在(3)中設置「真實」來源不會。我也嘗試設置base.Source到相同的值(新的BitmapImage(...)),但具有相同的結果。
  • 屬性(LanguageCodeResource)僅用於Button_Click事件處理程序中的簡潔性。

也許我的目標是錯誤的方向來解決這個問題?額外的反饋將不勝感激。

@NVM 這樣做的伎倆。非常感謝你!

對於任何有興趣的人,我附上我的正確代碼。有些繁瑣的DataContext數據類型是因爲我需要在我的真實程序中爲我的圖像和文本(來自XML文件)提供「兩個datacontexts」。

MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication2" 
    Title="MainWindow" Height="700" Width="525"> 
<Window.Resources> 
    <local:LocalizedImageSourceConverter x:Key="localizedImageSourceConverter" /> 
</Window.Resources> 
<StackPanel x:Name="layoutRoot"> 
    <Image x:Name="imgKoala" Source="{Binding Path=LanguageCode, Converter={StaticResource localizedImageSourceConverter}, ConverterParameter='Koala.(lang).jpg'}" Height="300" Stretch="Uniform" /> 
    <Image x:Name="imgPenguins" Source="{Binding Path=LanguageCode, Converter={StaticResource localizedImageSourceConverter}, ConverterParameter='Penguins.(lang).jpg'}" Height="300" Stretch="Uniform" /> 
    <Button Content="Don't click here!" Click="Button_Click" /> 
</StackPanel> 

MainWindow.cs.xaml

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

namespace WpfApplication1 
{ 
    public partial class MainWindow : Window 
    { 
     private string LanguageCodeValue 
     { 
      set 
      { 
       layoutRoot.DataContext = new 
       { 
        LanguageCode = value 
       }; 
      } 
     } 

     public MainWindow() 
     { 
      InitializeComponent(); 

      LanguageCodeValue = "en-GB"; 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      LanguageCodeValue = "fr-FR"; 
     } 
    } 

    public class LocalizedImageSourceConverter : IValueConverter 
    { 
     public object Convert(object values, Type targetType, object parameter, CultureInfo culture) 
     { 
      return ((string)parameter).Replace("(lang)", (string)values); 
     } 

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

當你某人的評論作出迴應,你應該把下面他們的評論,使它們notofied。 – NVM 2010-08-24 21:15:34

+0

我明白了。好的。感謝您的幫助伴侶。僅供參考,我不得不選擇multibind解決方案,以便能夠將ConverterParameter綁定到來自外部設置文件的值。 – 2010-08-25 06:32:16

+0

沒問題!很長時間以來一直在瘙癢,所以很高興能夠在這裏和那裏給出一些有用的答案。乾杯! – NVM 2010-08-27 01:41:53

回答

1

首先你應該停止使用 '語言代碼' 來命名,一應俱全。這是真的混亂:d

其次爲

<Window.Resources> 
    <local:LanguageCodeSetter x:Key="LanguageCode" LanguageCode="en-GB" /> 
</Window.Resources> 

作出任何意義

 public string LanguageCode 
    { 
     get 
     { 
      return _languageCode; 
     } 
     set 
     { 
      _languageCode = value; 
      NotifyPropertyChanged("LanguageCode"); 
     } 
    } 

應該是一個依賴屬性,而不是一個CLR屬性由inotify的支持...

編輯

我仍然我不知道LanguageCode屬性如何在資源部分工作。

反正已經瞭解你正試圖在這裏實現什麼,有一個非常簡單的解決方案

<Image Source="{Binding Path=LanguageCode, Converter={StaticResource localizedImageSourceConverter}, ConverterParameter='Koala.jpg'}"/> 

public class LocalizedImageSourceConverter : IValueConverter 
{ 
    public object Convert(object values, Type targetType, object parameter, CultureInfo culture) 
    { 
     string fileName = Path.GetFileNameWithoutExtension((string)parameter); 
     string extension = Path.GetExtension((string)parameter); 
     string languageCode = (string)values; 

     return string.Format("{0}{1}{2}", fileName, languageCode, extension); 
    } 

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

而不是綁定的源屬性文件路徑(URI),我將它綁定到該語言代碼屬性。 LanguageCode屬性應該在你的ViewModel或者你綁定的任何數據上下文對象中。

轉換器會將基礎圖像的路徑作爲參數,並將其與綁定的LanguageCodeProperty結合起來,爲您提供本地化路徑。而且,由於在綁定到datacontext中的LanguageCode屬性時,每當它發生更改時,所有圖像都將自動更新。請注意,轉換器參數不能被綁定。如果要綁定filePath和語言代碼,請使用多重綁定。

*有可能是代碼的語法錯誤,我只是想傳達的概念