【问题标题】:WPF binding from parent to child element从父元素到子元素的 WPF 绑定
【发布时间】:2013-10-21 11:39:52
【问题描述】:

这是我的 XAML

 <ListView x:Name="missingVariablesListView" ScrollViewer.CanContentScroll="True" HorizontalAlignment="Left" Height="320" Margin="81,28,0,0" VerticalAlignment="Top" Width="641" ItemsSource="{Binding}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Vertical">
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="ComponentID: " FontWeight="Bold" Foreground="Brown" />
                                <TextBlock Text="{Binding Name}"/>
                            </StackPanel>
                            <ItemsControl ItemsSource="{Binding Parameters}">
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <StackPanel>
                                            <StackPanel Orientation="Horizontal">
                                                <TextBlock Text="Variable Name: " Foreground="Green"/>
                                                <TextBlock Text="{Binding Name}"/>
                                                <TextBlock Text="   "/>                                           
                                                <TextBlock Text="Variable Value: " Foreground="Blue"/>
                                                <TextBlock Text="{Binding Value}"/>
                                            </StackPanel>
                                        </StackPanel>
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                                <ItemsControl.ItemContainerStyle>
                                    <Style >
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding IsMissing}" Value="false">
                                                <Setter Property="UIElement.Visibility" Value="Collapsed"/>                                                    
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                                </ItemsControl.ItemContainerStyle>
                            </ItemsControl>                           
                                <TextBlock Text="-----------------------------------------------------------------"/>
                        </StackPanel>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

这里是代码隐藏

  this.missingVariablesListView.DataContext = //Code to fill in the list View

涉及的类

public class Component
  {
  private ObservableCollection<ComponentParameter> parameters = new ObservableCollection<ComponentParameter>();
  public string Name
  {
    get;
    set;
  }

  public ObservableCollection<ComponentParameter> Parameters
  {
    get{return parameters;}
    set{parameters = value;}
   }
}



 public class ComponentParameter
 {
   public string Name
   {
    get;set;
   }

    public string Value
   {
    get;set;
   }

   public bool HasErrors
   {
    get;
    set;
   }

   public bool IsMissing
   {
    get;set;
   }

样本输出(目前)

ComponentID: Component1
--------------------------

ComponentID: Component2
VariableName:Var1 Variable Value:Val1
VariableName:Var2 Variable Value:Val2
-----------------------

ComponentID: Component3
-----------------------

ComponentID: Component4
-----------------------

我想要做的是,每当 itemsControl 中的内部元素的布尔 IsMissing 为真时,我想确保 StackPanel 中的 ComponentID 和 Name 属性(方向为水平)未显示在包含子元素的窗口。基本上,我试图找到一种方法来排除 isMissing 变量设置为 true 的特定 ComponentID 的整个描述。对此有何建议?

【问题讨论】:

  • 您的ItemsControl 中可能有多个项目,那么您要检查哪个项目的IsMissing 属性?
  • 嗨@Gehho 是的,有多个项目,我想检查该 ItemsControl 中的所有项目。只要 IsMissing 对于我想要将它们排除在用户面前的所有项目都是错误的。我只显示将 isMissing 设置为 true 的项目。
  • @elgonzo 我将对象包装为observationCollection,因此这些事情应该在幕后隐式完成。谢谢你告诉我
  • @Sike:不。ObservableCollection 仅监视和通知集合本身的更改。它不会知道(因此也不会通知)存储在集合中的对象的属性是否以及何时发生更改。

标签: c# .net wpf xaml wpf-controls


【解决方案1】:

我会考虑在Component 类中添加一个属性IsAnyParameterMissing

public class Component
{
    private ObservableCollection<ComponentParameter> parameters = new ObservableCollection<ComponentParameter>();
    public string Name
    {
      get;
      set;
    }

    public ObservableCollection<ComponentParameter> Parameters
    {
        get{return parameters;}
        set{parameters = value;}
    }

    public bool IsAnyParameterMissing
    {
        get { return this.Parameters.Any(param => param.IsMissing); }
    }
}

然后将可见性绑定到这个属性:

<StackPanel Orientation="Horizontal" Visibility="{Binding IsAnyParameterMissing, Converter={BooleanToVisibilityConverter}}">
    <TextBlock Text="ComponentID: " FontWeight="Bold" Foreground="Brown" />
    <TextBlock Text="{Binding Name}"/>
</StackPanel>

仅当集合中的任何Parameters 的IsMissing 属性等于true 时,才会显示StackPanel。请注意,如果更改任何项目的 IsMissing 属性,这不会更改可见性!这需要一些额外的工作。

编辑:请注意,{BooleanToVisibilityConverter} 可能需要调整,具体取决于您可用的转换器。不过应该是一项简单的任务。

【讨论】:

  • 是的,这似乎适用于外面的财产。谢谢 gehho
【解决方案2】:

我注意到的一件事是您没有将属性(例如“isMissing”)实现为 DependencyProperty。您也不会通过 INotifyPropertyChanged 使用属性更改通知。

您必须实现两者中的任何一个,否则属性的更改将不会通过绑定传播。也就是说,触发器不会触发...

【讨论】:

  • @Elogonzo 感谢似乎还有一些工作要做。谢谢:)
【解决方案3】:

您可以使用BooleanToVisibilityConverter 为您隐藏这些项目,尽管您可能需要为此更改您的属性或添加一个新的IsPresent 属性:

Resources:

<Converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" 
    IsInverted="True" />

在你的ListView.ItemTemplate

<StackPanel Orientation="Horizontal" Visibility="{Binding IsMissing, Converter={
    StaticResource BoolToVisibilityConverter}}">
    <TextBlock Text="ComponentID: " FontWeight="Bold" Foreground="Brown" />
    <TextBlock Text="{Binding Name}"/>
</StackPanel>

自定义BoolToVisibilityConverterIsInverted 属性:

[ValueConversion(typeof(bool), typeof(Visibility))]
public class BoolToVisibilityConverter : IValueConverter
{
    public bool IsInverted { get; set; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || value.GetType() != typeof(bool)) return null;
        bool boolValue = IsInverted ? !(bool)value : (bool)value;
        return boolValue ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || value.GetType() != typeof(Visibility)) return null;
        if (IsInverted) return (Visibility)value != Visibility.Visible;
        return (Visibility)value == Visibility.Visible;
    }
}

现在只需一分钟即可实施。我已经更新了上面的 XAML 示例以使用它。

【讨论】:

  • 抱歉@Sike12,我把我的自定义转换器和现在包含在 .NET 中的转换器搞混了……你应该能够在不添加的情况下使用该转换器XML 命名空间:
  • 在我的自定义 BoolToVisibilityConverter 中,我有一个 IsInverted 属性可以允许这样做,但我认为标准的 .NET 没有这个选项......所以要么创建一个新的返回!IsMissingIsPresent 属性,或带有IsInverted 属性的implement your own converter
  • 但这不起作用,因为IsMissing 属性是在ComponentParameter 类上定义的,而StackPanelDataContextComponent 类的一个实例。这没有IsMissing 属性!如果 任何ComponentParameter 实例IsMissing 属性为true,Sike12 希望StackPanel 不可见。
  • 如果他像我在上一条评论中建议的那样使用IsInverted 属性实现自定义BoolToVisibilityConverter,它将起作用。
  • @Sike12,不管您当前的问题是什么,如果您要继续编写 WPF,那么无论如何您都应该构建大量您自己的自定义 Converter 类。实现 Converter 课程只需要一分钟,它们是 WPF 的重要组成部分……如果您错过了它们所提供的功能,那将是一种耻辱。我已编辑我的答案以包含我的Converter 以供您将来使用。
猜你喜欢
  • 1970-01-01
  • 2017-07-20
  • 2011-01-27
  • 2014-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-19
  • 1970-01-01
相关资源
最近更新 更多