转换器无法处理矩形填充属性

时间:2013-09-25 08:11:17

标签: c# wpf xaml mvvm

我在bool值(Rectangle)上绑定Fill Fill="{Binding Path=IsSelected, Converter={StaticResource rectangleFillConverter}}"属性,并抛出一个空异常。我检查了属性(IsSelected)的值不为null。当我从Fill属性中删除Converter时,它可以工作。这是我的代码:

XAML

<Rectangle Width="{Binding Duration}" Height="20" Tag="{Binding .}" IsEnabled="{Binding Path=IsEnabled}" Fill="{Binding Path=IsSelected, Converter={StaticResource rectangleFillConverter}}" ToolTip="{Binding Path=Shift}" MouseDown="LabelShift_MouseDown"></Rectangle>

转换器

public class RectangleControlFillConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            SolidColorBrush brush; 
            bool b= (bool)value;
            if (b)
                brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#5C8FFF"));
            else
                brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#73E34D"));

            return brush;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

静态资源

<converters:RectangleControlFillConverter x:Key="rectangleFillConverter"/>

属性

private bool _isSelected;
        public bool IsSelected
        {
            get { return _isSelected; }
            set 
            { 
                _isSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }

ItemsControl哪里是矩形,此转换器工作Converter={StaticResource timeToPositionConverter}}"

<ItemsControl Name="icSchedule" ItemsSource="{Binding .}" Grid.Row="1" Grid.Column="1">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal" Margin="0"/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                                <ItemsControl ItemsSource="{Binding Path=icw}" Tag="{Binding .}" Margin="0,10,0,0"><!--Margin="3"Grid.Row="1" Grid.Column="1"  Background="DarkGray" BorderThickness="1" BorderBrush="White"-->
                                <ItemsControl.ItemsPanel>
                                    <ItemsPanelTemplate>
                                        <Canvas IsItemsHost="True" />
                                    </ItemsPanelTemplate>
                                </ItemsControl.ItemsPanel>
                                <ItemsControl.ItemContainerStyle>
                                    <Style TargetType="{x:Type ContentPresenter}">
                                        <Setter Property="Canvas.Left" Value="{Binding Path=Start, Converter={StaticResource timeToPositionConverter}}" />
                                        <Setter Property="Canvas.Top" Value="{Binding Path=Index}" />
                                    </Style>
                                </ItemsControl.ItemContainerStyle>
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate DataType="TimeLineEntry">
                                        <Border BorderThickness="1" BorderBrush="DarkGray">
                                                <Rectangle Width="{Binding Duration}" Height="20" Tag="{Binding .}" IsEnabled="{Binding Path=IsEnabled}" Fill="{Binding Path=IsSelected, Converter={StaticResource rectangleFillConverter}}" ToolTip="{Binding Path=Shift}" MouseDown="LabelShift_MouseDown"> 

                                             </Rectangle>                                     
                                        </Border>

                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                        </DataTemplate> 
                    </ItemsControl.ItemTemplate>
                </ItemsControl>

这是关于对象的类是矩形绑定(icw是那些对象的列表)

public partial class ScheduleItem
    {
        public string Shift 
        { 
            get
            {
                //string s = ((DateTime)DateFrom).ToString("dd.MM.yyyy") + " " + ((TimeSpan)TimeFrom).ToString() + " - " + ((DateTime)DateTo).ToString("dd.MM.yyyy") + " " + ((TimeSpan)TimeTo).ToString();
                String s = String.Format("{0}.{1} {2}:{3} - {4}.{5} {6}:{7}", FullDateFrom.Day, FullDateFrom.Month, FullDateFrom.Hour, FullDateFrom.Minute, FullDateTo.Day, FullDateTo.Month, FullDateTo.Hour, FullDateTo.Minute);
                return s;
            }
        }

        private DateTime FullDateFrom
        {
            get
            {
                DateTime dt = ((DateTime)DateFrom).AddHours(((TimeSpan)TimeFrom).Hours).AddMinutes(((TimeSpan)TimeFrom).Minutes);
               return dt;
            }
        }

        private DateTime FullDateTo
        {
            get
            {
                DateTime dt = ((DateTime)DateTo).AddHours(((TimeSpan)TimeTo).Hours).AddMinutes(((TimeSpan)TimeTo).Minutes);
                return dt;
            }
        }

        public string Name { get; set; }
        public DateTime Start { get { return FullDateFrom; } }
        private int index;
        public int Index 
        { 
            get 
            {
                if (CampaignPerson != null)
                    return CampaignPerson.Index;
                else
                    return index;
            }
            set 
            {
                index = value;
            } 
        }
        public int Duration 
        { 
            get 
            { 
                TimeSpan dt = FullDateTo - FullDateFrom;

                return (dt.Days* 92) + (dt.Hours*4); 
            }
        }

        public bool IsEnabled 
        {
            get { return (FullDateFrom > DateTime.Now); }
        }

        private bool _isSelected;
        public bool IsSelected
        {
            get { return _isSelected; }
            set 
            { 
                _isSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }
        #region setters

        partial void OnTimeFromChanged()
        {
            OnPropertyChanged("Duration");
            OnPropertyChanged("Start");
        }

        partial void OnTimeToChanged()
        {
            OnPropertyChanged("Duration");
            OnPropertyChanged("Start");
        }

        partial void OnDateFromChanged()
        {
            OnPropertyChanged("Duration");
            OnPropertyChanged("Start");
        }

        partial void OnDateToChanged()
        {
            OnPropertyChanged("Duration");
            OnPropertyChanged("Start");
        }

        #endregion



    }

ViewModel类icShedule是对此类

的集合进行绑定
public class ScheduleExtension
    {
        public ICollectionView icw {get; set;}

        public ScheduleExtension(CampaignPerson cp)
        {
            campainPerson = cp;
            scheduleItemsList.CollectionChanged += new NotifyCollectionChangedEventHandler(_scheduleItemsList_CollectionChanged);

            icw = CollectionViewSource.GetDefaultView(scheduleItemsList);
            icw.Filter = ScheduleFilter;
        }

        private CampaignPerson _campainPerson;
        public CampaignPerson campainPerson
        {
            get { return _campainPerson; }
            set 
            { 
                _campainPerson = value;
                scheduleItemsList = new ObservableCollection<ScheduleItem>(_campainPerson.ScheduleItem.Where(p=>p.active)); 
            }
        }

        private DateTime _currentDate;
        public DateTime CurrentDate
        {
            get { return _currentDate; }
            set 
            {
                _currentDate = value;
                icw.Refresh();
                //CurrrentScheduleItemsList = new ObservableCollection<ScheduleItem>(scheduleItemsList.Where(p => p.active && ((DateTime)p.DateFrom).Month == CurrentDate.Month && ((DateTime)p.DateFrom).Year == CurrentDate.Year));

                //OnPropertyChanged("CurrentScheduleItemsList");
            }
        }

        public ObservableCollection<ScheduleItem> scheduleItemsList;



        void _scheduleItemsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {

        }

        private bool ScheduleFilter(object item)
        {
            if (CurrentDate != null)
            {
                ScheduleItem si = item as ScheduleItem;
                return (CurrentDate.Month == ((DateTime)si.DateFrom).Month && CurrentDate.Year == ((DateTime)si.DateFrom).Year);
            }
            return false;
        }
    }

3 个答案:

答案 0 :(得分:1)

尝试将<DataTemplate DataType="TimeLineEntry">更改为<DataTemplate DataType="ScheduleItem">。也许ScheduleItemTimeLineEntry(您只发布了部分类的一部分),但请尝试它是否有效。

问题也可能是由于您处理集合的方式造成的。在构造函数中,您说:

icw = CollectionViewSource.GetDefaultView(scheduleItemsList);
icw.Filter = ScheduleFilter;

然后在campainPerson属性中说:

scheduleItemsList = new ObservableCollection<ScheduleItem>(_campainPerson.ScheduleItem.Where(p=>p.active));

您必须使用相同的集合对象(通过清除它并添加新项目),或者创建新的ICollectionView并将其分配给icw(因此您必须重复这两个对象)创建新ObservableCollection后来自构造函数的行。也试一试。

答案 1 :(得分:0)

我不认为问题来自转换器,即使你删除它时一切正常。这是我的测试应用程序。

MainWindow.xaml

<Window x:Class="MVVMTests.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    xmlns:local="clr-namespace:MVVMTests"
    Background="{StaticResource {x:Static SystemColors.ControlBrushKey}}"
>
<Window.Resources>
    <ResourceDictionary>
        <local:RectangleControlFillConverter x:Key="rectangleFillConverter" />
    </ResourceDictionary>
</Window.Resources>

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

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <CheckBox Content="toto" IsChecked="{Binding IsSelected}" />
        <Rectangle Fill="{Binding Path=IsSelected, Converter={StaticResource rectangleFillConverter}}" Grid.Row="1" />
    </Grid>
</Window>

ViewModel

namespace MVVMTests
{
    public class MainWindowViewModel : NotificationObject
    {
        private Boolean isSelected;

        public MainWindowViewModel()
        {
            isSelected = true;
        }

        public Boolean IsSelected
        {
            get { return this.isSelected; }
            set
            {
                this.isSelected = value;
                this.RaisePropertyChanged<Boolean>(() => IsSelected);
            }
        }
    }
}

和召集人

namespace MVVMTests
{
    [ValueConversion(typeof(Boolean), typeof(SolidColorBrush))]
    public class RectangleControlFillConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            SolidColorBrush brush;
            bool b = (bool)value;
            if (b)
                brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#5C8FFF"));
            else
                brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#73E34D"));

            return brush;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

使用这个简单的代码,我们可以看到转换器不是问题(窗口开关丑陋蓝/丑绿),绑定工作正常。

这不是一个解决方案,但这告诉我们问题在其他地方......

答案 2 :(得分:0)

矩形转换器仍无法处理任何属性。

这对我有用Fill="{Binding Path=CurrentColor}"

以及ScheduleItem中的此更改

 private bool _isSelected;
        public bool IsSelected
        {
            get { return _isSelected; }
            set 
            { 
                _isSelected = value;
                if(_isSelected)
                    CurrentColor = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#73E34D"));
                else
                    CurrentColor = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#5C8FFF"));
                OnPropertyChanged("CurrentColor");
            }
        }

        private SolidColorBrush _currentColor = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#5C8FFF"));
        public SolidColorBrush CurrentColor
        {
            get { return _currentColor; }
            set { _currentColor = value; }
        }

谢谢你们的时间和建议。