2016-06-15 2 views
2

Я заселение мой выпадающий с TimeZone информацию, используя ниже:Использование привязки данных, отображение времени в текстовое поле на основе выбранного TimeZone в ComboBox

MainWindow.xaml.cs

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

внизу от XAML:

<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"/> 

Я также смог показать соответствующее значение в текстовом поле , используя этот код:

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 и ссылающийся на него в конструкторе MainWindow, но я не мог получить даже выпадающий заселена.

Я действительно хочу понять и использовать магию привязки данных C#.

+0

Вы хотите связать все значения в Combobox справа? – Balaji

+0

В combobox будет отображаться список часовых поясов, и я хочу показать соответствующее время в текстовом поле в зависимости от выбранного вами временного часового пояса. –

+1

«Я действительно хочу понять и использовать магию привязки данных C#». Если вы действительно этого хотите, вы должны пойти на решение без каких-либо обработчиков событий в коде, как показано в других ответах. – Clemens

ответ

1

В стандартном MVVM ap proach, вы должны создать класс модели представления с двумя свойствами, одну коллекцию только для чтения для всех TimeZoneInfos и одну для выбранного в данный момент TimeZone.

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 вашего окна к экземпляру модели представления и связать ComboBox и TextBox свойства, как показано в этом XAML:

<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> 

, где привязка к использований текста собственности a Конвертер:

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

В вашем ComboBox, связать его ItemSource к ReadOnlyCollection,

<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"/> 

Теперь время, которое вы хотите отобразить привязку к свойству,

<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-файл теперь,

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 упростит ваш код. Только для этого вопроса, на самом деле вам не нужно писать View Model в CS.

<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(); 
    } 
} 
Смежные вопросы