ComboBox не показывает значение, к которому привязан SelectedItem - PullRequest
0 голосов
/ 24 сентября 2019

Я пытаюсь синхронизировать поле со списком со свойством:

<ComboBox SelectedItem="{Binding StrokeSwatch}"...

Эта работа исключает, что поле со списком остается пустым (элементы здесь, если коробка открыта, но неттекущий / выбранный элемент), пока я не выберу значение вручную.

enter image description here

На нем должны отображаться красный образец и имя:

enter image description here
Я не могу найти причину: свойство SelectedItem связано с (StrokeSwatch) имеет значение, которое используется строкой, но поле со списком не реагируетк этому значению.

Изучая WPF, был бы признателен за небольшую помощь в понимании.

Код ...

    <Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="300">

        <Window.DataContext>
            <local:ViewModel/>
        </Window.DataContext>

        <StackPanel Margin="10">
            <StackPanel Orientation="Horizontal" Margin="10">
                <TextBlock Text="Stroke:"/>
                <ComboBox Margin="10,0,0,0" ItemsSource="{Binding SwatchesByName}" SelectedItem="{Binding StrokeSwatch}">
                    <ComboBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <Rectangle Width="25" Fill="{Binding Brush}"/>
                                <TextBlock Margin="10,0,0,0" Text="{Binding Name}"/>
                            </StackPanel>
                        </DataTemplate>
                    </ComboBox.ItemTemplate>
                </ComboBox>
            </StackPanel>

            <Line Margin="10" X1="0" Y1="0" X2="200" Y2="100"
                  Stroke="{Binding StrokeSwatch.Brush}"
                  StrokeThickness="2"/>
        </StackPanel>
    </Window>

C #:

    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Media;

    namespace WpfApp1 {
        public partial class MainWindow : Window {
            public MainWindow () {
                InitializeComponent ();
            }
        }

        public class ViewModel : INotifyPropertyChanged {
            Swatch strokeSwatch;
            public IEnumerable<Swatch> SwatchesByName { get => Swatches.ByName; }
            public Swatch StrokeSwatch { get => strokeSwatch; set { strokeSwatch = value; RaisePropertyChanged (); } }
            public event PropertyChangedEventHandler PropertyChanged;

            public ViewModel () {
                StrokeSwatch = Swatches.ColorToSwatch (Colors.Red);
            }

            void RaisePropertyChanged ([CallerMemberName] string propertyName = null) {
                PropertyChanged?.Invoke (this, new PropertyChangedEventArgs (propertyName));
            }
        }

        static class Swatches {
            public static IEnumerable<Swatch> ByName { get; }

            static Swatches () {
                ByName = from PropertyInfo pi in typeof (Colors).GetProperties ()
                         orderby pi.Name
                         select new Swatch (pi.Name, (Color) pi.GetValue (null, null));
            }

            public static Swatch ColorToSwatch (Color color) {
                return ByName.First (sw => sw.Color == color);
            }
        }

        public class Swatch {
            SolidColorBrush brush;
            public string Name { get; }
            public Color Color { get; }
            public SolidColorBrush Brush { get { if (brush == null) brush = new SolidColorBrush (Color); return brush; } }

            public Swatch (string name, Color color) {
                Name = name;
                Color = color;
            }
        }
    }

Ответы [ 2 ]

1 голос
/ 24 сентября 2019

Позвоните ToArray() на IEnumerable<Swatch>, чтобы материализовать коллекцию ByName:

static Swatches()
{
    ByName = (from PropertyInfo pi in typeof(Colors).GetProperties()
              orderby pi.Name
              select new Swatch(pi.Name, (Color)pi.GetValue(null, null))).ToArray();
}
0 голосов
/ 24 сентября 2019

Прежде всего вы должны использовать свойство observableCollection и вернуть List в вашем классе Swatche

public class ViewModel : INotifyPropertyChanged
{
    Swatch strokeSwatch;

    public ObservableCollection<Swatch> SwatchesByName
    {
        get => _swatchesByName;
        set { _swatchesByName = value; RaisePropertyChanged();}
    }

    private ObservableCollection<Swatch> _swatchesByName;

    public Swatch StrokeSwatch 
    { 
        get => strokeSwatch; 
        set { strokeSwatch = value; RaisePropertyChanged(); }
    }
    public event PropertyChangedEventHandler PropertyChanged;

    public ViewModel()
    {
        SwatchesByName = new ObservableCollection<Swatch>(Swatches.ByName);
        StrokeSwatch = Swatches.ColorToSwatch(Colors.Red);
    }

    void RaisePropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

static class Swatches
{
    public static List<Swatch> ByName { get; }

    static Swatches()
    {
        var list = from PropertyInfo pi in typeof(Colors).GetProperties()
            orderby pi.Name
            select new Swatch(pi.Name, (Color)pi.GetValue(null, null));
        ByName = list.ToList();
    }

    public static Swatch ColorToSwatch(Color color)
    {
        return ByName.First(sw => sw.Color == color);
    }
}

public class Swatch
{
    SolidColorBrush brush;
    public string Name { get; }
    public Color Color { get; }

    public SolidColorBrush Brush
    {
        get { if (brush == null) brush = new SolidColorBrush(Color); return brush; }
    }

    public Swatch(string name, Color color)
    {
        Name = name;
        Color = color;
    }
}
...