2016-06-15 6 views
2

で選択したタイムゾーンに基づいて、テキストボックスに表示時間を使う:私は以下を使用して、タイムゾーン情報と私のコンボボックスを移入していますデータバインディング、コンボボックス

MainWindow.xaml.cs

private void Window_Loaded(object sender, RoutedEventArgs e) 
{ 
    ReadOnlyCollection<TimeZoneInfo> TimeZones = TimeZoneInfo.GetSystemTimeZones(); 
    this.DataContext = TimeZones; 
    cmb_TZ.SelectedIndex = 1; 
} 

<ComboBox x:Name="cmb_TZ" ItemsSource="{Binding}" Grid.Row="0" Grid.Column="2" Height="28.5" Margin="10,65.375,30.945,0" VerticalAlignment="Top" d:LayoutOverrides="LeftMargin, RightMargin, TopMargin, BottomMargin" SelectionChanged="ComboBox_Selection"/> 

以下XAMLからのものです210

また、私はこのコードを使用することによりテキストボックスに対応する値を示すことができています:

private void ComboBox_Selection(object Sender, SelectionChangedEventArgs e) 
{ 
    var cmbBox = Sender as ComboBox; 
    DateTime currTime = DateTime.UtcNow; 
    TimeZoneInfo tst = (TimeZoneInfo)cmbBox.SelectedItem; 
    txt_Time.Text = TimeZoneInfo.ConvertTime(currTime, TimeZoneInfo.Utc, tst).ToString("HH:mm:ss dd MMM yy"); 
} 

txt_Timeは私のテキストボックスです。そのためのXAMLコードは次のとおりです。

<TextBox x:Name="txt_Time" Grid.Row="0" Grid.Column="1" Height="28.5" Margin="26.148,65.375,28.13,0" TextWrapping="Wrap" VerticalAlignment="Top" d:LayoutOverrides="LeftMargin, RightMargin, TopMargin, BottomMargin"/> 

私の質問は:データバインディングを使用してこれを実現する方法は

ありますか? 私は上記のストレートフォワード方式を使用してこれを行うことができます。しかし、私はこの計算がデータバインディングを介して実行できるかどうか疑問に思っていましたか?

私はC#/ WPFに新しいですし、私は単純なクラスを作成してもINotifyPropertyChangedのを使用してクラスとメインウィンドウのコンストラクタでそれを参照しようとしたが、私もコンボボックスが人口得ることができませんでした。

私は本当に理解して、C#のデータバインディングの魔法を使用したいと思います。あなたのComboBox

+0

Comboboxのすべての値を正しくバインドしますか? – Balaji

+0

コンボボックスにはタイムゾーンのリストがあり、CBで選択したタイムゾーンに応じて、対応する時刻をテキストボックスに表示したいと考えています。 –

+1

"C#のデータバインディングの魔法を理解して使用したいと思っています。"本当にそれが必要な場合は、他の回答に示されているように、コードの中にイベントハンドラがないソリューションを探すべきです。 – Clemens

答えて

1

標準のMVVM ap Proachでは、2つのプロパティ、すべてのTimeZoneInfoの読み取り専用コレクション、現在選択されているTimeZoneの1つのプロパティを持つビューモデルクラスを作成します。

public class ViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    public ReadOnlyCollection<TimeZoneInfo> TimeZones { get; } 
     = TimeZoneInfo.GetSystemTimeZones(); 

    private TimeZoneInfo selectedTimeZone = TimeZoneInfo.Local; 

    public TimeZoneInfo SelectedTimeZone 
    { 
     get { return selectedTimeZone; } 
     set 
     { 
      selectedTimeZone = value; 
      PropertyChanged?.Invoke(this, 
       new PropertyChangedEventArgs("SelectedTimeZone")); 
     } 
    } 
} 

あなたはビューモデルのインスタンスにあなたの窓ののDataContextを設定し、このXAMLに示すようにコンボボックスとテキストボックスのプロパティをバインドすることができます。

Textプロパティの用途への結合
<Window ...> 
    <Window.DataContext> 
     <local:ViewModel/> 
    </Window.DataContext> 
    <Window.Resources> 
     <local:TimeZoneConverter x:Key="TimeZoneConverter" /> 
    </Window.Resources> 
    <StackPanel> 
     <ComboBox ItemsSource="{Binding TimeZones}" 
        SelectedItem="{Binding SelectedTimeZone}" /> 
     <TextBox Text="{Binding SelectedTimeZone, 
         Converter={StaticResource TimeZoneConverter}}"/> 
    </StackPanel> 
</Window> 

このようなコンバーター:

public class TimeZoneConverter : IValueConverter 
{ 
    public object Convert(
     object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return value == null ? string.Empty : TimeZoneInfo 
      .ConvertTime(DateTime.UtcNow, TimeZoneInfo.Utc, (TimeZoneInfo)value) 
      .ToString("HH:mm:ss dd MMM yy"); 
    } 

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

、あなたがプロパティにバインドを表示したい時は、

<TextBox x:Name="txt_Time" Text="{Binding TimeZome}" Grid.Row="0" Grid.Column="1" Height="28.5" Margin="26.148,65.375,28.13,0" TextWrapping="Wrap" VerticalAlignment="Top" d:LayoutOverrides="LeftMargin, RightMargin, TopMargin, BottomMargin"/> 

対応するCSファイルが今現在そのReadOnlyCollectionItemSource

<ComboBox x:Name="cmb_TZ" ItemsSource="{Binding TimeZoneList}" Grid.Row="0" Grid.Column="2" Height="28.5" Margin="10,65.375,30.945,0" VerticalAlignment="Top" d:LayoutOverrides="LeftMargin, RightMargin, TopMargin, BottomMargin" SelectionChanged="ComboBox_Selection"/> 

を結合し、

public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      this.DataContext = this; 
     } 


     private void Window_Loaded(object sender, RoutedEventArgs e) 
     { 
      ReadOnlyCollection<TimeZoneInfo> TimeZones = TimeZoneInfo.GetSystemTimeZones(); 
      TimeZoneList = TimeZones; 
      cmb_TZ.SelectedIndex = 1; 
     } 

     private void ComboBox_Selection(object sender, SelectionChangedEventArgs e) 
     { 
      var cmbBox = sender as ComboBox; 
      DateTime currTime = DateTime.UtcNow; 
      TimeZoneInfo tst = (TimeZoneInfo)cmbBox.SelectedItem; 
      TimeZome = TimeZoneInfo.ConvertTime(currTime, TimeZoneInfo.Utc, tst).ToString("HH:mm:ss dd MMM yy"); 
     } 

     private string _TimeZome; 
     public string TimeZome 
     { 
      get { return _TimeZome; } 
      set 
      { 
       if (value == _TimeZome) 
        return; 

       _TimeZome = value; 
       this.OnPropertyChanged("TimeZome"); 
      } 
     } 
     private ReadOnlyCollection<TimeZoneInfo> _TimeZoneList; 
     public ReadOnlyCollection<TimeZoneInfo> TimeZoneList 
     { 
      get { return _TimeZoneList; } 
      set 
      { 
       if (value == _TimeZoneList) 
        return; 

       _TimeZoneList = value; 
       this.OnPropertyChanged("TimeZoneList"); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     public void OnPropertyChanged(string propertyName) 
     { 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 
1

ObjectDataProviderを使用するとコードが簡単になります。ちょうどこの質問のために、実際にCSにView Modelを書く必要はありません。

<Window x:Class="WpfApplication2.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:src="clr-namespace:System;assembly=mscorlib" 
     xmlns:sys="clr-namespace:System;assembly=System.Core" 
     xmlns:local="clr-namespace:WpfApplication2" 
     Title="MainWindow" Height="350" Width="525"> 
    <Window.Resources> 
     <ObjectDataProvider x:Key="timezone" ObjectType="{x:Type sys:TimeZoneInfo}" MethodName="GetSystemTimeZones"></ObjectDataProvider> 
     <local:TimeZoneConverter x:Key="timezoneconverter"/> 
    </Window.Resources> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="*"/> 
     </Grid.ColumnDefinitions> 
     <ComboBox x:Name="cmb_TZ" ItemsSource="{Binding Source={StaticResource timezone}}" Height="30" /> 
     <TextBlock x:Name="txt_Time" Grid.Column="1" Text="{Binding ElementName=cmb_TZ, Path=SelectedValue, Converter={StaticResource timezoneconverter}}"/> 
    </Grid> 
</Window> 

また、Clemensのコンバーターが必要です。

public class TimeZoneConverter : IValueConverter 
{ 
    public object Convert(
     object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return value == null ? string.Empty : TimeZoneInfo 
      .ConvertTime(DateTime.UtcNow, TimeZoneInfo.Utc, (TimeZoneInfo)value) 
      .ToString("HH:mm:ss dd MMM yy"); 
    } 

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