基于具有不同背景颜色的属性(+方法返回值)重建ComboBoxItems

时间:2016-07-07 14:13:39

标签: c# wpf xaml

我将这些学习要点作为 app.xaml 文件中的资源:

<x:Array x:Key="StudyPoints" Type="local:StudyPointItem">
    <local:StudyPointItem Number = "0" Title = "No study point assigned" />
    <local:StudyPointItem Number = "1" Title = "Accurate Reading" />
    <local:StudyPointItem Number = "2" Title = "Words Clearly Spoken" />
    <local:StudyPointItem Number = "3" Title = "Correct Pronunciation" />
    <local:StudyPointItem Number = "4" Title = "Fluent Delivery" />
    <local:StudyPointItem Number = "5" Title = "Appropriate Pausing" />
    <local:StudyPointItem Number = "6" Title = "Proper Sense Stress" />
    <local:StudyPointItem Number = "7" Title = "Principal Ideas Emphasized" />
    <local:StudyPointItem Number = "8" Title = "Suitable Volume" />
    <local:StudyPointItem Number = "9" Title = "Modulation" />
    <local:StudyPointItem Number = "10" Title = "Enthusiasm" />
    <local:StudyPointItem Number = "11" Title = "Warmth And Feeling" />
    <local:StudyPointItem Number = "12" Title = "Gestures and Facial Expressions" />
    <local:StudyPointItem Number = "13" Title = "Visual Contact" />
    <local:StudyPointItem Number = "14" Title = "Naturalness" />
    <local:StudyPointItem Number = "15" Title = "Good Personal Appearance" />
    <local:StudyPointItem Number = "16" Title = "Poise" />
    <local:StudyPointItem Number = "17" Title = "Use of Microphone" />
    <local:StudyPointItem Number = "18" Title = "Use of Bible in Replying" />
    <local:StudyPointItem Number = "19" Title = "Use of Bible Encouraged" />
    <local:StudyPointItem Number = "20" Title = "Scriptures Effectively Introduced" />
    <local:StudyPointItem Number = "21" Title = "Scriptures Read With Proper Emphasis" />
    <local:StudyPointItem Number = "22" Title = "Scriptures Correctly Applied" />
    <local:StudyPointItem Number = "23" Title = "Practical Value Made Clear" />
    <local:StudyPointItem Number = "24" Title = "Choice of Words" />
    <local:StudyPointItem Number = "25" Title = "Use of an Outline" />
    <local:StudyPointItem Number = "26" Title = "Logical Development of Material" />
    <local:StudyPointItem Number = "27" Title = "Extemporaneous Delivery" />
    <local:StudyPointItem Number = "28" Title = "Conversational Manner" />
    <local:StudyPointItem Number = "29" Title = "Voice Quality" />
    <local:StudyPointItem Number = "30" Title = "Interest Shown in the Other Person" />
    <local:StudyPointItem Number = "31" Title = "Respect Shown to Others" />
    <local:StudyPointItem Number = "32" Title = "Expressed With Conviction" />
    <local:StudyPointItem Number = "33" Title = "Tactful Yet Firm" />
    <local:StudyPointItem Number = "34" Title = "Upbuilding And Positive" />
    <local:StudyPointItem Number = "35" Title = "Repetition for Emphasis" />
    <local:StudyPointItem Number = "36" Title = "Theme Developed" />
    <local:StudyPointItem Number = "37" Title = "Main Points Made to Stand Out" />
    <local:StudyPointItem Number = "38" Title = "Interest - Arousing Introduction" />
    <local:StudyPointItem Number = "39" Title = "Effective Conclusion" />
    <local:StudyPointItem Number = "40" Title = "Accuracy of Statement" />
    <local:StudyPointItem Number = "41" Title = "Understandable to Others" />
    <local:StudyPointItem Number = "42" Title = "Informative to Your Audience" />
    <local:StudyPointItem Number = "43" Title = "Use of Assigned Material" />
    <local:StudyPointItem Number = "44" Title = "Effective Use of Questions" />
    <local:StudyPointItem Number = "45" Title = "Illustrations / Examples That Teach" />
    <local:StudyPointItem Number = "46" Title = "Illustrations From Familiar Situations" />
    <local:StudyPointItem Number = "47" Title = "Effective Use of Visual Aids" />
    <local:StudyPointItem Number = "48" Title = "Reasoning Manner" />
    <local:StudyPointItem Number = "49" Title = "Sound Arguments Given" />
    <local:StudyPointItem Number = "50" Title = "Effort To Reach the Heart" />
    <local:StudyPointItem Number = "51" Title = "Accurately Timed, Properly Proportioned" />
    <local:StudyPointItem Number = "52" Title = "Effective Exhortation" />
    <local:StudyPointItem Number = "53" Title = "Audience Encouraged and Strengthened" />
</x:Array>

在我的 ViewModel 中,我有几种方法可用于构建列表的两个过滤版本:

private void InitReadingStudyPointsList()
{
    ReadingStudyPointsList = new List<StudyPointItem>();

    StudyPointItem[] arrayStudyItems = (StudyPointItem[])Application.Current.Resources["StudyPoints"];

    for (int iStudyNumber = 0; iStudyNumber < 18; iStudyNumber++)
        ReadingStudyPointsList.Add(arrayStudyItems[iStudyNumber]);

}

private void InitStudentStudyPointsList()
{
    StudentStudyPointsList = new List<StudyPointItem>();

    StudyPointItem[] arrayStudyItems = (StudyPointItem[])Application.Current.Resources["StudyPoints"];

    for (int iStudyNumber = 0; iStudyNumber < 52; iStudyNumber++)
    {
        if (iStudyNumber != 7)
            StudentStudyPointsList.Add(arrayStudyItems[iStudyNumber]);
    }
}

并且,在主窗口中,我在ComboBoxes中使用这些筛选列表作为项目源。例如:

<ComboBox DataContext="{Binding DataContext, ElementName=oclmEditor}"
              ItemsSource="{Binding ReadingStudyPointsList}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Number}"/>
                <TextBlock Text=" - "/>
                <TextBlock Text="{Binding Title}"/>
            </StackPanel>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

现在,我的 ViewModel Student类型的属性。当您在DataGrid上选择学生时,它会保持最新状态。

Student有一个公共方法:

bool IsWorkingOnStudyPoint(int iStudy)

目前,我的ComboBox看起来像是:

Combo

这就是我想要实现的目标:

  

当用户选择学生时,ComboBox会更新学习点列表,以便将IsWorkingOnStudy(x)作为true返回的任何内容都将ComboBoxItem背景设置为黄色。手动构建的例子:

Combo with highlighting

我正在努力建立正确的方法来解决这个问题。

更新

我到了那里:

<ComboBox DataContext="{Binding DataContext, ElementName=oclmEditor}"
              ItemsSource="{Binding ReadingStudyPointsList}">
    <ComboBox.ItemContainerStyle>
        <Style TargetType="ComboBoxItem">
            <Setter Property="Tag" Value="{Binding Number}" />
            <Setter Property="Background">
                <Setter.Value>
                    <MultiBinding Converter="{StaticResource StudyPointWorkingOn}">
                        <Binding RelativeSource="{RelativeSource Self}" Path="Tag"/>
                        <Binding/>
                    </MultiBinding>
                </Setter.Value>
            </Setter>
        </Style>
    </ComboBox.ItemContainerStyle>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="{Binding Number}"/>
                <TextBlock Text=" - "/>
                <TextBlock Text="{Binding Title}"/>
            </StackPanel>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

对于ValueConverter(测试代码):

namespace OCLMEditor.ValueConverters
{
    class StudyPointWorkingOn : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            int iStudyNumber = (int)values[0];
            Console.WriteLine(values[1].ToString());
            if(iStudyNumber % 3 == 0)            
                return (SolidColorBrush)System.Windows.Media.Brushes.Aqua;

            return null;

            //throw new NotImplementedException();
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

但是我的第二个参数<Binding />是错误的。那是StudyPointItem对象,我想要传递的是为ComboBox本身指定的内容:

<ComboBox DataContext="{Binding DataContext, ElementName=oclmEditor}"

具体来说,我想传递第二个绑定值:DataContext.SelectedStudentItem

有意义吗?但我无法做到对。但至少我现在可以获得细胞颜色。只是不是我想要的,直到我可以传递正确的DataContext

更新2

我现在绑定正确,所以我有正确的DataContext:

<ComboBox DataContext="{Binding DataContext, ElementName=oclmEditor}"
              ItemsSource="{Binding ReadingStudyPointsList}">
    <ComboBox.ItemContainerStyle>
        <Style TargetType="ComboBoxItem">
            <Setter Property="Tag" Value="{Binding Number}" />
            <Setter Property="Background">
                <Setter.Value>
                    <MultiBinding Converter="{StaticResource StudyPointWorkingOn}">
                        <Binding RelativeSource="{RelativeSource Self}" Path="Tag"/>
                        <Binding Path="DataContext" ElementName="oclmEditor" />
                    </MultiBinding>
                </Setter.Value>
            </Setter>
        </Style>
    </ComboBox.ItemContainerStyle>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="{Binding Number}"/>
                <TextBlock Text=" - "/>
                <TextBlock Text="{Binding Title}"/>
            </StackPanel>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

但我现在有另一个问题。它只构建下拉列表一次的内容。但我需要它是动态的:

public Student SelectedStudentItem
{
    get
    {
        return _SelectedStudentItem;
    }
    set
    {
        // We need to remove this item from the previous student history
        if (_SelectedStudentItem != null)
            _SelectedStudentItem.History.Remove(Meeting.DateMeeting);

        _SelectedStudentItem = value;
        if (_SelectedStudentItem == null)
            return;

        _EditStudentButtonClickCommand.RaiseCanExecuteChanged();
        _DeleteStudentButtonClickCommand.RaiseCanExecuteChanged();
        OnPropertyChanged("SelectedStudentItem");

        if (ActiveStudentAssignmentType == StudentAssignmentType.BibleReadingMain)
            _Meeting.BibleReadingMainName = _SelectedStudentItem.Name;
        else if (ActiveStudentAssignmentType == StudentAssignmentType.BibleReadingClass1)
            _Meeting.BibleReadingClass1Name = _SelectedStudentItem.Name;
        else if (ActiveStudentAssignmentType == StudentAssignmentType.BibleReadingClass2)
            _Meeting.BibleReadingClass2Name = _SelectedStudentItem.Name;
    }
}

每当SelectedStudentItem属性发生变化时,我都希望`ComboBoxItem'背景发生相应的变化。

2 个答案:

答案 0 :(得分:1)

存档有很多解决方案。

a)您可以将StudyPointItem包装到视图模型中,为视图模型提供Color属性,并将ComboBoxItem的背景属性绑定到该颜色。

b)您可以将项目直接绑定到background属性,并使用转换器为这些项目创建相应的颜色。

c)如果项目的属性具有特定值,则可以使用触发器设置颜色。

......我确信WPF提供了更多的可能性。

就个人而言,我使用转换器来执行此类任务,因为它们非常灵活,并且不会使用任何“转换属性”炸毁视图模型。

答案 1 :(得分:0)

这就是我开始工作的方式:

<ComboBox DataContext="{Binding DataContext, ElementName=oclmEditor}"
              ItemsSource="{Binding ReadingStudyPointsList}">
    <ComboBox.ItemContainerStyle>
        <Style TargetType="ComboBoxItem">
            <Setter Property="Tag" Value="{Binding Number}" />
            <Style.Triggers>
                <DataTrigger Value="True">
                    <DataTrigger.Binding>
                        <MultiBinding Converter="{StaticResource StudyPointWorkingOn}">
                            <Binding RelativeSource="{RelativeSource Self}" Path="Tag"/>
                            <Binding Path="DataContext.SelectedStudentItem" ElementName="oclmEditor" UpdateSourceTrigger="PropertyChanged" />
                        </MultiBinding>
                    </DataTrigger.Binding>
                    <Setter Property="Background" Value="Red"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ComboBox.ItemContainerStyle>
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Number}"/>
                <TextBlock Text=" - "/>
                <TextBlock Text="{Binding Title}"/>
            </StackPanel>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>