2013-11-12 2 views
0

У меня есть ListPicker, который имеет несколько различных вариантов значений цвета. Когда выбрано значение цвета, я хотел бы сразу показать этот цвет на некоторых элементах в представлении. Я немного запутался в том, как лучше всего это сделать.Как изменить цвет элемента сразу в представлении

EditPage.xaml

<phone:PhoneApplicationPage.Resources> 
    <DataTemplate x:Name="ListPickerItemTemplate"> 
     <StackPanel Orientation="Horizontal"> 
      <Image Source="{Binding Image}" Width="50" Height="37.59"/> 
      <TextBlock Text="{Binding Name}" Foreground="{Binding Brush}" Margin="12,0,0,0" TextWrapping="Wrap"/> 
     </StackPanel> 
    </DataTemplate> 
</phone:PhoneApplicationPage.Resources> 

... 

<toolkit:ListPicker x:Name="themeListPicker" Header="Theme" FullModeHeader="Theme" CacheMode="BitmapCache" 
             SelectionChanged="themeListPicker_SelectionChanged" 
             ItemTemplate="{StaticResource ListPickerItemTemplate}" 
             FullModeItemTemplate="{StaticResource ListPickerFullModeItemTemplate}"/> 

EditPage.xaml.cs

protected override void OnNavigatedTo(NavigationEventArgs e) 
    { 
     base.OnNavigatedTo(e); 

     themeList = new List<Theme>(); 
     themeList.Add(new Theme() { Image = new BitmapImage(new Uri("/Assets/Themes/Indigo.png", UriKind.Relative)), Name = "indigo", Color = Color.FromArgb(255, 106, 0, 255) }); 
     themeList.Add(new Theme() { Image = new BitmapImage(new Uri("/Assets/Themes/Cyan.png", UriKind.Relative)), Name = "cyan", Color = Color.FromArgb(255, 27, 161, 226) }); 
     themeList.Add(new Theme() { Image = new BitmapImage(new Uri("/Assets/Themes/Cobalt.png", UriKind.Relative)), Name = "cobalt", Color = Color.FromArgb(255, 0, 80, 239) }); 

     themeListPicker.ItemsSource = themeList; 
    } 

private void themeListPicker_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     if (themeListPicker.SelectedItem == null) 
      return; 

     CurrentTheme = themeListPicker.SelectedItem as Theme; 
    } 

public class Theme : NotifyingObject 
{ 
    public BitmapImage Image { get; set; } 
    public string Name { get; set; } 
    public Color Color { get; set; } 
    public SolidColorBrush Brush 
    { 
     get 
     { 
      return new SolidColorBrush(Color); 
     } 
    } 

    private Theme _currentTheme; 
    public Theme CurrentTheme 
    { 
     get 
     { 
      return _currentTheme; 
     } 

     set 
     { 
      if (value == _currentTheme) return; 
      _currentTheme = value; 
      NotifyPropertyChanged("CurrentTheme"); 
     } 
    } 
} 

Я не уверен, если я ставлю это вместе правильно. Кроме того, как я могу сразу показать текущий выбранный цвет как цвет объекта или какое-либо свойство объекта в представлении? У меня есть пара ToggleSwitches, панель слайдера и т. Д., Которые должны сразу менять цвета при выборе нового элемента в ListPicker.

EDIT **

EditPage.xaml

<phone:PhoneApplicationPage.Resources>  
    <DataTemplate x:Name="ListPickerItemTemplate"> 
     <StackPanel Orientation="Horizontal"> 
      <Image Source="{Binding CurrentTheme.Image}" Width="50" Height="37.59"/> 
      <TextBlock Text="{Binding CurrentTheme.Name}" Foreground="{Binding CurrentTheme.Brush}" Margin="12,0,0,0" TextWrapping="Wrap"/> 
     </StackPanel> 
    </DataTemplate> 
    <DataTemplate x:Name="ListPickerFullModeItemTemplate"> 
     <StackPanel Orientation="Horizontal"> 
      <Image Source="{Binding CurrentTheme.Image}" Width="50" Height="37.59"/> 
      <TextBlock Text="{Binding CurrentTheme.Name}" Foreground="{Binding CurrentTheme.Brush}" Margin="12,0,0,0" TextWrapping="Wrap"/> 
     </StackPanel> 
    </DataTemplate> 
</phone:PhoneApplicationPage.Resources> 

.. 

<toolkit:ListPicker x:Name="themeListPicker" Header="Theme" FullModeHeader="Theme" 
             ItemsSource="{Binding Themes}" CacheMode="BitmapCache" 
             SelectionChanged="themeListPicker_SelectionChanged" 
             ItemTemplate="{StaticResource ListPickerItemTemplate}" 
             FullModeItemTemplate="{StaticResource ListPickerFullModeItemTemplate}"/> 

<Slider x:Name="Slider" Minimum="1" Maximum="6" Margin="12,20,12,0" Foreground="{Binding CurrentTheme.Brush}" 
        ValueChanged="Slider_ValueChanged" Value="1"/> 

EditPage.xaml.cs

protected override void OnNavigatedTo(NavigationEventArgs e) 
    { 
     base.OnNavigatedTo(e); 

     themeList = new List<Theme>(); 
     themeList.Add(new Theme() { Image = new BitmapImage(new Uri("/Assets/Themes/Indigo.png", UriKind.Relative)), Name = "indigo", Color = Color.FromArgb(255, 106, 0, 255) }); 
     themeList.Add(new Theme() { Image = new BitmapImage(new Uri("/Assets/Themes/Cyan.png", UriKind.Relative)), Name = "cyan", Color = Color.FromArgb(255, 27, 161, 226) }); 
     themeList.Add(new Theme() { Image = new BitmapImage(new Uri("/Assets/Themes/Cobalt.png", UriKind.Relative)), Name = "cobalt", Color = Color.FromArgb(255, 0, 80, 239) }); 

     var viewModel = new ThemeViewModel(); 
     viewModel.Themes = themeList; 
     DataContext = viewModel; 
    } 

private void themeListPicker_SelectionChanged(object sender, SelectionChangedEventArgs e) 
    { 
     //var theme = (sender as ListPicker); 
     //MessageBox.Show("Chosen theme: " + e.AddedItems[0].ToString()); 

     if (themeListPicker.SelectedItem == null) 
      return; 

     //How to save the current theme color in IsoStore? 
     var CurrentTheme = themeListPicker.SelectedItem as Theme; 
     //Custom Settings class to save current color in IsoStore 
     Settings.themeBrush.Value = CurrentTheme.Brush; 
    } 

ThemeViewModel.cs

private Theme _currentTheme;   
    public Theme CurrentTheme 
    { 
     get { return _currentTheme; } 
     set 
     { 
      if (value == _currentTheme) return; 
      _currentTheme = value; 
      NotifyPropertyChanged("CurrentTheme"); 
     } 
    } 

    private IList<Theme> _themes; 
    public IList<Theme> Themes 
    { 
     get { return _themes; } 
     set 
     { 
      if (value == _themes) return; 
      _themes = value; 
      NotifyPropertyChanged("Themes"); 
     } 
    } 

Theme.cs

public BitmapImage Image { get; set; } 
    public string Name { get; set; } 
    public Color Color { get; set; } 
    public SolidColorBrush Brush 
    { 
     get 
     { 
      return new SolidColorBrush(Color); 
     } 
    } 

Settings.cs

//Theme 
    public static readonly Setting<SolidColorBrush> themeBrush = new Setting<SolidColorBrush>("themeBrush", new SolidColorBrush(Color.FromArgb(255, 106, 0, 255))); 

С этим новым редактирования и настройки CurrentTheme в связывании, такие как Foreground="{Binding CurrentTheme.Brush}" его, как элементы в ListPicker невидимы, но когда я удалить CurrentTheme от связывания, например, в Foreground="{Binding Brush}" Элементы ListPicker отображаются со связанными цветами? Вдоль этих строк не используется или не используется CurrentTheme при привязке переднего плана к управлению Slider, поэтому передний план кажется просто прозрачным. Кроме того, как я могу изменить границу ListPicker таким образом, когда будет создан новый выбор ListPicker? Кроме того, мне нужно сохранить текущий цвет темы, чтобы элементы в представлении имели одинаковый цвет при возврате в приложение. Каким будет лучший способ присвоения элементам постоянного цвета после выбора нового элемента в ListPicker? У меня есть класс Settings, показанный выше, который может хранить значение кисти в IsoStore, но как я могу применить его к элементам в представлении после вашего решения (обычно я бы сделал это в явно указанном коде)?

+0

Чтобы изменить цвет элемента управления, можно связать 'Brush' с свойством' Foreground' этого элемента управления, для простых элементов управления в любом случае. Для более сложных элементов управления, таких как «ListPicker», вам нужно создать «ControlTemplate», как я предложил в другом ответе (http://stackoverflow.com/questions/19898395/how-to-change-listpicker-selection- шаблон), который вы, вероятно, хотите отменить или выбрать как ответ, потому что вы использовали мой код в этом вопросе ... :) Действительно, вы должны рассмотреть MVVM, как предлагает @Iain. – venerik

+1

о да, я забыл проголосовать! сделают сейчас! Благодарю. – Matthew

+0

Я следил за вашим предложением, рассматривая MVVM как способ пойти и обновил мое решение выше. Однако у меня есть вопрос о том, как сохранить выбранный цвет из ListPicker и применить его к элементам в представлении на постоянной основе (и сразу). Кроме того, у меня есть стиль в 'App.xaml', в котором свойство принимает значение цвета, как бы применить и этот цвет? – Matthew

ответ

1

Я думаю, вы найдете это намного проще, если вы примете подход MVVM следующим образом.

Создайте страницуViewModel, чтобы представить все ваши данные. например:

public class PageViewModel : NotifyingObject 
{ 
    public Theme CurrentTheme 
    { 
     get { return _currentTheme; } 
     set 
     { 
      if (value == _currentTheme) return; 
      _currentTheme = value; 
      NotifyPropertyChanged("CurrentTheme"); 
     } 
    } 
    public IList<Theme> Themes 
    { 
     get { return _themes; } 
     set 
     { 
      if (value == _themes) return; 
      _themes = value; 
      NotifyPropertyChanged("Themes"); 
     } 
    } 
} 

Теперь назначить новый PageViewModel своего DataContext:

protected override void OnNavigatedTo(NavigationEventArgs e) 
{ 
    base.OnNavigatedTo(e); 

    themeList = new List<Theme>(); 
    themeList.Add(new Theme() { Image = new BitmapImage(new Uri("/Assets/Themes/Indigo.png", UriKind.Relative)), Name = "indigo", Color = Color.FromArgb(255, 106, 0, 255) }); 
    themeList.Add(new Theme() { Image = new BitmapImage(new Uri("/Assets/Themes/Cyan.png", UriKind.Relative)), Name = "cyan", Color = Color.FromArgb(255, 27, 161, 226) }); 
    themeList.Add(new Theme() { Image = new BitmapImage(new Uri("/Assets/Themes/Cobalt.png", UriKind.Relative)), Name = "cobalt", Color = Color.FromArgb(255, 0, 80, 239) }); 

    var viewModel = new PageViewModel(); 
    viewModel.Themes = themeList; 
    DataContext = viewModel; 
} 

Теперь в вашем XAML привязать список вашего подборщик для вашей модели представления:

<toolkit:ListPicker ... ItemsSource="{Binding Themes}" .../> 

Теперь вы можете связать любого другие элементы, которые вы хотите, например:

<TextBlock Text="{Binding CurrentTheme.Name}" Foreground="{Binding CurrentTheme.Brush}"> 

EDIT:

Убедитесь, что CurrentTheme обновляется путем добавления этой привязки к ListPicker:

<toolkit:ListPicker ... SelectedItem="{Binding CurrentTheme, Mode=TwoWay}" > 

Ваши DataTemplate s не должны иметь CurrentTheme в их привязок, как вы заметили , Привязки в DataTemplates должны относиться к отдельному элементу в ListPicker (то есть что-нибудь на Theme)

+0

OK Я обновил свое решение соответственно, хотя у меня все еще есть пара вопросов и вопросов. Я добавил изменение выше, чтобы отразить мои изменения. Не могли бы вы рассказать о моих проблемах после вашего решения выше? – Matthew

+0

Вы, кажется, не обновляете CurrentTheme на ViewModel. Я сделаю надпись выше. – Iain

+0

ОК, который работал, и я также удалил событие «SelectionChanged». Наверное, мне интересно, как сохранить сохраненный выбранный цвет в «ListPicker» и применить его к элементам в представлении на этой странице и других. У меня есть параметр Settings.themeBrush.Value', чтобы удерживать выбранный цвет навсегда, но где я должен назначить это и как лучше всего привязать его к элементам View? У меня есть стиль заголовка в App.xaml.cs, которому необходимо назначить цвет, а также другие элементы в представлении (некоторые из которых заданы переднем плане в XAML, а другие - в коде, например, для цветов с включенными/отключенными ToggleSwitch) , – Matthew

1

Если я правильно понимаю вас, вы не можете просто установить Foreground элементы пользовательского интерфейса в вашем взгляде на SelectionChanged событии? Он мгновенно отразит изменения.

private void themeListPicker_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    if (themeListPicker.SelectedItem == null) 
     return; 

    CurrentTheme = themeListPicker.SelectedItem as Theme; 
    SolidColorBrush b = CurrentTheme.Brush; 
    //Change foreground of toggle switch, slider etc you want here 
    toggle.Foreground = b; 
    slider.Foreground = b; 
} 

Если элементы пользовательского интерфейса, которые вы хотите изменить связаны с ListPicker тогда MVVM это лучший способ пойти. Хотя вам нужно будет установить DataContext всего контейнера в свой класс, и это приведет к определенным зависимостям от доступа к свойствам элементов пользовательского интерфейса. Вам нужно будет привязать все, что вам нужно, к классу Theme, например. TextBlock 's text, foreground и т. Д. Если вы сделаете это, убедитесь, что у всех есть INotifyPropertyChanged, унаследованный, чтобы отразить любые динамические изменения.

+0

Я пробовал ваше решение, и это, безусловно, сработало, хотя я бы хотел использовать метод MVVM, он выглядит намного более динамичным. Я редактировал мое решение выше, имея несколько проблем внизу. Возможно, вы могли бы дать некоторое представление? (Я несколько новичок в MVVM, когда дело касается привязки элементов класса к представлению). – Matthew

Смежные вопросы