【问题标题】:WPF How to set an array as a propertyWPF 如何将数组设置为属性
【发布时间】:2019-09-16 16:31:21
【问题描述】:

我正在使用 WPF,并且我有一组椭圆,我想在运行时更改其颜色。这是我的代码

Color[] ellipsecolor = new Color[13];
public event PropertyChangedEventHandler PropertyChanged;

    private void onPropertyChanged(String propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

我想这样做:

Ellipse x:Name="Spot5" Fill="Gray" StrokeThickness="6" Width="40" 
Height="40" Margin="219,211,241,249" MouseDown="Ellipse_MouseDown"
  ..
 SolidColorBrush Color= "{Binding ellipsecolor[0],IsAsync=True}"/>

但我不确定我是否能做到这一点。 这个可以吗?

【问题讨论】:

  • 你有一个可以改变颜色的椭圆,还是有 13 个不同的椭圆,所有这些椭圆都有不同的不改变颜色?

标签: c# arrays wpf


【解决方案1】:

无需使用数组。您可以在 xaml 中对 ObservableCollection 进行索引,类似于对数组进行索引。但是,您的集合类型需要实现 INotifyPropertyChanged。理想情况下,您将创建一个从 Color 继承的类型并实现 INotifyPropertyChanged,但由于 Color 类是密封的,所以这是不可能的。

但是,用您自己的类型包装 Color 应该可以。

 class MyColor : INotifyPropertyChanged
 {        
        public event PropertyChangedEventHandler PropertyChanged;

        private Color _color;

        public Color color
        {
            get
            {
               return _color;
            }

            set
            {
               _color = value;
               OnPropertyChanged("color");
            }
        }

        void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
  }   

在适当的地方实例化集合。

   ObservableCollection<MyColor> ellipseColors = new ObservableCollection<MyColor>();

然后绑定到 xaml 中索引的 MyColor 对象的颜色属性。

Color= "{Binding Path=ellipseColors[0].color, IsAsync=True}"/>

感谢这篇文章的一些想法。 Binding to an array element

更新:

public partial class Wafer : UserControl
{
    private string _waferLocation;

    ObservableCollection<MyColor> ellipseColors;

    private void WaferLoaded(object sender, RoutedEventArgs e)
    {
      ellipseColors = new ObservableCollection<MyColor>();          

      for (int i = 0; i < 13; i++)
      {
          ellipseColors.Add(new MyColor { color = Brushes.Gray });               
      }

    }

    class MyColor : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private SolidColorBrush _color;

        public SolidColorBrush color
        {
            get
            {
                return _color;
            }

            set
            {
                _color = value;
                OnPropertyChanged("color");
            }
        }

        void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

【讨论】:

  • 他有不止一个椭圆,所以他不能在 XAML 中做[0]
  • 不确定我是否关注。不管有多少个椭圆,每个都可以绑定到他们想要的集合中的任何索引,不是吗?
  • 是的,但是您使用的是 WPF。你不应该那样做。 ItemsControl 是正确的做法。
【解决方案2】:

不确定您使用的是哪个 MVVM 框架,但一般方法是这样的:

  1. 在 ViewModel 层中,为您的椭圆创建一个 VM:

    public class EllipseVM : ObservableObject
    {
        private Color _Color;
        public Color Color
        {
          get => _Color;
          set => Set(ref _Color, value);
        }
    
        private double _X;
        public double X
        {
          get => _X;
          set => Set(ref _X, value);
        }
    
        private double _Y;
        public double Y
        {
          get => _Y;
          set => Set(ref _Y, value);
        }
    }
    
  2. 在您的主 ViewModel 中创建这些椭圆的集合:

    public class MainVM : ViewModelBase
    {
        private ObservableCollection<EllipseVM> _Ellipses;
        public ObservableCollection<EllipseVM> Ellipses
        {
          get => _Ellipses;
          set => Set(ref _Ellipses, value);
        }
    }
    
  3. 在您的视图层中,创建一个与此集合绑定的ItemsControl

    <ItemsControl ItemsSource="{Binding Ellipses}">
      <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
          <Canvas />
        </ItemsPanelTemplate>
      </ItemsControl.ItemsPanel>
    
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <Ellipse Fill="{Binding Color}" Width="40" Height="40" />
        </DataTemplate>
      </ItemsControl.ItemTemplate>
    
      <ItemsControl.ItemContainerStyle>
        <Style>
          <Setter Property="Canvas.Left" Value="{Binding X}" />
          <Setter Property="Canvas.Top" Value="{Binding Y}" />
        </Style>  
      </ItemsControl.ItemContainerStyle>
    </ItemsControl>
    

积分

  1. 您可以在运行时将任意数量的省略号添加到您的集合中。由于您的集合是ObservableCollection,因此视图层会自动更新。
  2. ItemsControl 使用 Canvas 作为其面板,它允许您使用 X、Y 坐标定位椭圆。这允许您在运行时放置或移动椭圆。
  3. 请注意,Canvas 属性需要通过ItemContainerStyle 设置,而不是通过ItemTemplate。这是因为ItemsControl 为您的集合中的每个项目生成一个包装器元素。然后将您的 DataTemplate 放置在该包装器内,因此您需要设置该包装器元素的位置,这正是 ItemContainerStyle 所做的。
  4. 如果您的 VM 层不能使用 Color 类(因为它是一个视图级别库),您可以使用将 EllipseVM 的 Color 属性设置为 int 类型。然后,您需要在 View 层中创建一个转换器,将 int 值转换为 Color
  5. 我使用了来自 MVVM Light 的辅助类(例如 ViewModelBaseObservableObject)。如果您使用的是不同的框架,请将它们替换为对应的部分。
  6. 您必须将视图的DataContext 设置为MainVM。您可以通过 MVVM Light 中的 ViewModelLocator 来实现。您也可以直接在 XAML 或代码隐藏中执行此操作。

【讨论】:

  • 我没有使用 MVVM
  • @Nia2:好的。如果你在 WPF 中做任何严肃的事情,你应该这样做。
猜你喜欢
  • 2012-12-04
  • 2014-07-01
  • 1970-01-01
  • 2014-02-04
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多