简体   繁体   English

在WPF列表框中设置复选框项目的前景色

[英]Set foreground text color of checkbox items in a wpf listbox

I have several lists containing data from a db. 我有几个包含数据库数据的列表。 The listboxes serves as filters for a chart, and the appearance of the listboxes should change depending on what is selected in other listboxes. 列表框用作图表的筛选器,并且列表框的外观应根据在其他列表框中选择的内容而变化。

Here is a simplified example of what I'm trying to do specifically: 这是我要具体执行的简化示例:

Class Region
{
public int RegionID { get; set; }
public string RegionName { get; set; }
}

Class Country
{
public int CountryID { get; set; }
public string CountryName { get; set; }
public int RegionID { get; set; }
}

private void fillListBoxes()
{
List<Region> allRegions = getRegions();
lstRegionsFilter.ItemsSource = allRegions;
}

A country obviously belongs to a region, and I also have for example Ports, which is then located in a country etc etc. 一个国家显然属于一个地区,例如,我也有港口,然后位于一个国家中,等等。

All listbox items are checkboxes defined like this: 所有列表框项目都是如下定义的复选框:

<ListBox Name="lstRegionsFilter">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding Path=RegionName}"
                      Tag="{Binding Path=RegionID}" 
                      Click="CheckBox_Click"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

As items in any listbox is clicked they are added to a list of filters which will filter the data displaying the chart. 单击任何列表框中的项目后,它们将被添加到过滤器列表中,这些过滤器将过滤显示图表的数据。 So for example if "Europe" is selected under Regions then all Countries that belongs to Europe should be colored differently in the listbox for countries, for example blue. 因此,例如,如果在“地区”下选择了“欧洲”,则属于欧洲的所有国家/地区在国家/地区列表中的颜色应不同,例如蓝色。

So in code I want to loop through the check boxes in the country-listbox and set its foreground color to something depending on if the value displayed/tagged to that checkbox is a country that belongs to the selected Region so typically in a foreach loop. 所以在代码中,我想遍历country-listbox中的复选框并将其前景色设置为某种颜色,具体取决于在该复选框中显示/标记的值是否是属于所选Region的国家,因此通常在foreach循环中。 However the items in the listbox is of type Region so how can I access the underlying checkbox? 但是,列表框中的项目类型为Region,所以如何访问基础复选框? This should be pretty basic stuff I know, but its driving me nuts! 这应该是我知道的非常基本的东西,但是让我发疯了!

Try this: 尝试这个:

public class Region : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private bool isChecked;

    private void OnPropertyChaned(string property)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property));
    }

    public int RegionID { get; set; }
    public string RegionName { get; set; }

    public bool IsChecked
    {
        get { return isChecked; }
        set
        {
            if (isChecked != value)
            {
                isChecked = value;
                OnPropertyChaned("IsChecked");
            }
        }
    }
}

public class Country : INotifyPropertyChanged
{
    private readonly Region parentRegion;

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string property)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(property));
    }

    public Country(Region parent)
    {
        parentRegion = parent;
        parentRegion.PropertyChanged += ParentChanged;
    }

    private void ParentChanged(object sender, PropertyChangedEventArgs e)
    {
        if(e.PropertyName.Equals("IsChecked"))
        {
            OnPropertyChanged("IsParentChecked");
        }
    }

    public int CountryID { get; set; }
    public string CountryName { get; set; }
    public int RegionID { get { return parentRegion.RegionID; }}
    public bool IsParentChecked
    {
        get { return parentRegion.IsChecked; }
    }
}

and the xaml: 和xaml:

This is for the Regions: 这是针对地区的:

<ListBox Name="lstRegionsFilter">
<ListBox.ItemTemplate>
    <DataTemplate>
        <CheckBox Content="{Binding Path=RegionName}"
                  Tag="{Binding Path=RegionID}"
                  IsChecked="{Binding Path=IsChecked}"
                  Click="CheckBox_Click"/>
    </DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

And this is for the Countries 这是给国家的

<ListBox Name="lstCountriesFilter">
<ListBox.ItemTemplate>
    <DataTemplate>
        <CheckBox ...
                  Foreground={Binding IsParentChecked, Converter={StaticResource boolToBrushConverter}"/>
                  ...
                  />
    </DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Note: 注意:

  • You need to implement the Converter class (see here ) 您需要实现Converter类(请参阅此处
  • Add the converter to the xaml as StaticResouce 将转换器作为StaticResouce添加到xaml

The Country Checkboxes forecolor will change automatically if the regions IsChecked property changed (from the ui or from code-behind), so no loop needed. 如果区域IsChecked属性发生了更改(从ui或从后台代码),则Country Checkboxes前景色将自动更改,因此不需要循环。

I haven't tried it, probably you can find mistakes but I wanted to show the "phylosophy" 我没有尝试过,可能您会发现错误,但是我想展示“系统论”

Hope it helps 希望能帮助到你

If i get you right, your plan is to have a country highlighted in its region coulor if its region is selected ? 如果我答对了,您的计划是如果选择了区域,则在其区域库中突出显示一个国家? Rq 1 : You don't have to loop through checkBoxes to know which region is selected : this is the purpose of the binding that the values of the binded collection themselves will be affected. Rq 1:您不必遍历复选框即可知道选择了哪个区域:这是绑定的目的,因为绑定集合本身的值将受到影响。
Rq2 : If you change the values in code, you have to implement INotifyPropertyChanged in your region class for the UI to be updated. Rq2:如果更改代码中的值,则必须在区域类中实现INotifyPropertyChanged才能更新UI。
How to do it ? 怎么做 ?
1. have a static dictionnary of RegionId --> Boolean. 1.具有RegionId->布尔值的静态字典。
2. Whenever a RegionId gets selected/unselected, update that dictionnary and raise a static event 'SelectionDictionnaryUpdated'. 2.每当选择或取消选择RegionId时,请更新该字典并引发静态事件“ SelectionDictionnaryUpdated”。
3. Now add a notifying property 'IsOwnerRegionSelected' in your Country class. 3.现在在您的Country类中添加一个通知属性'IsOwnerRegionSelected'。 it will look in the dictionnary to say if corresponding region is selected or not. 它会在词典中说出是否选择了相应区域。
4. add property 'CountryRegionColor' in your Country class. 4.在国家类中添加属性“ CountryRegionColor”。 It will return the color based on RegionId and, say a RegionId -> Color static dictionnary. 它将返回基于RegionId的颜色,例如,一个RegionId-> Color静态字典。
5. add a Trigger, inside your DataTemplate, and a DataTrigger that will switch color beetween white and CountryRegionColor, depending on IsOwnerRegionSelected value. 5.在您的数据模板中添加一个触发器,以及一个数据触发器,该触发器将根据IsOwnerRegionSelected值在白色和CountryRegionColor之间切换颜色。
6. In the constructor of a country, add a handler to SelectionDictionnaryUpdated that will NotifyPropertyChanged on the "IsOwnerRegionSelected". 6.在一个国家的构造函数中,向SelectionDictionnaryUpdated添加一个处理程序,该处理程序将在“ IsOwnerRegionSelected”上添加NotifyPropertyChanged。

that's it ! 而已 !

  1. you can make it with non-shared dictionnary (each country having a RegionId --> Boolean dictionnary property that you inject in constructor) 您可以使用非共享字典来实现(每个国家/地区都具有您要在构造函数中注入的RegionId->布尔字典属性)
  2. you can make things simpler by having 'CurrentCoulor': notifying property that will return either white or CountryRegionColor depending if it is selected or not. 您可以通过使用'CurrentCoulor'使事情变得更简单:通知属性,该属性将返回white或CountryRegionColor,取决于是否选中它。 just bind the Background of your list to that property, and notifyCurrentCoulor changed when you catch SelectionDictionnaryUpdated. 只需将列表的Background绑定到该属性,并在捕获SelectionDictionnaryUpdated时notifyCurrentCoulor发生更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM