在WPF中使用DataTrigger时的绑定问题

时间:2011-08-25 06:03:36

标签: .net wpf xaml data-binding datagrid

我的WPF项目中的绑定存在问题。相关的XAML如下:

<dg:DataGrid.RowDetailsTemplate>
    <DataTemplate>
      <StackPanel>
        <TextBlock Name="txtnoitems" Text="No Records Found" Visibility="Collapsed"></TextBlock>
      </StackPanel>
      <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding HasItems, RelativeSource={RelativeSource Self}}" Value="False">
          <Setter  TargetName="txtnoitems" Property="Visibility" Value="Visible"></Setter>
        </DataTrigger>
      </DataTemplate.Triggers>
    </DataTemplate>
  </dg:DataGrid.RowDetailsTemplate>

我要做的是在TextBlockDataGrid.HasItems时显示false。这不是出于某种原因。

任何人都可以看到我的问题可能是什么?

1 个答案:

答案 0 :(得分:1)

根据评论中的假设进行编辑:

如果正如@bathineni所说,当集合中没有项目时,你想要在DataGrid上方显示一个框,你可能需要使用RowDetailsTemplate以外的机制来实现这一点。

我能想到的两个例子是设置DataGrid的样式,使其包含一个突出显示的TextBlock来显示此消息,另一个例子是创建一个包含DataGrid的网格和要在顶部显示的Message。

示例一: 设置DataGrid的样式

你可以找到一个very nice tutorial here来向你展示如何设置DataGrid内部的样式,类似于Samuel在这里的样式,总共有四个。

在DataGrid模板中,包围Grid对象中的所有内容并创建要在其中显示的消息。

例如:(请原谅长代码段)

        <Style TargetType="{x:Type DataGrid}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGrid}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition />
                            </Grid.RowDefinitions>

                            <Border
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        SnapsToDevicePixels="True"
                        Grid.Row="1"
                        Padding="{TemplateBinding Padding}">
                                <ScrollViewer Focusable="false" Name="DG_ScrollViewer">
                                    <ScrollViewer.Template>
                                        <ControlTemplate TargetType="{x:Type ScrollViewer}">
                                            <Grid>
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="Auto"/>
                                                    <RowDefinition Height="*"/>
                                                    <RowDefinition Height="Auto"/>
                                                </Grid.RowDefinitions>

                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="Auto"/>
                                                    <ColumnDefinition Width="*"/>
                                                    <ColumnDefinition Width="Auto"/>
                                                </Grid.ColumnDefinitions>

                                                <!--Left Column Header Corner -->
                                                <Button
                                                    Style="{StaticResource selectAllButtonTemplate}"
                                                    Command="{x:Static DataGrid.SelectAllCommand}"
                                                    Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=CellsPanelHorizontalOffset}"
                                                    Focusable="false"
                                                    Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.All}}" />

                                                <!--Column Headers-->
                                                <Primitives:DataGridColumnHeadersPresenter 
                                                    Grid.Column="1"
                                                    Name="PART_ColumnHeadersPresenter"
                                                    Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Column}}"/>

                                                <!--DataGrid content-->
                                                <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Grid.Row="1" Grid.ColumnSpan="2" CanContentScroll="{TemplateBinding CanContentScroll}" />

                                                <Border Name="noItemsBorder" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden" SnapsToDevicePixels="True" Background="Coral" BorderBrush="DarkRed" BorderThickness="1" Grid.Row="1" Grid.ColumnSpan="2">
                                                    <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="No items to display" Margin="20" />
                                                </Border>

                                                <ScrollBar
                                                    Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" Name="PART_VerticalScrollBar"
                                                    Orientation="Vertical"
                                                    Maximum="{TemplateBinding ScrollableHeight}"
                                                    ViewportSize="{TemplateBinding ViewportHeight}"
                                                    Value="{Binding Path=VerticalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
                                                    Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>

                                                <Grid Grid.Row="2" Grid.Column="1">
                                                    <Grid.ColumnDefinitions>
                                                        <ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=NonFrozenColumnsViewportHorizontalOffset}"/>
                                                        <ColumnDefinition Width="*"/>
                                                    </Grid.ColumnDefinitions>
                                                    <ScrollBar 
                                                        Grid.Column="1"
                                                        Name="PART_HorizontalScrollBar"
                                                        Orientation="Horizontal"
                                                        Maximum="{TemplateBinding ScrollableWidth}"
                                                        ViewportSize="{TemplateBinding ViewportWidth}"
                                                        Value="{Binding Path=HorizontalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
                                                        Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
                                                </Grid>
                                            </Grid>

                                            <ControlTemplate.Triggers>
                                                <DataTrigger Binding="{Binding Path=HasItems, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" Value="False">
                                                    <Setter TargetName="noItemsBorder" Property="Visibility" Value="Visible" />
                                                </DataTrigger>
                                            </ControlTemplate.Triggers>
                                        </ControlTemplate>
                                    </ScrollViewer.Template>
                                    <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                                </ScrollViewer>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>

            <Style.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}">Transparent</SolidColorBrush>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}">Transparent</SolidColorBrush>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}">Black</SolidColorBrush>
            </Style.Resources>

            <Style.Triggers>
                <Trigger Property="IsGrouping" Value="true">
                    <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                </Trigger>
            </Style.Triggers>
        </Style>

在上面的示例中,您可以看到noItemsBorder对象,当ScrollContentPresenter x:Name="PART_ScrollContentPresenter"为false(通过使用触发器显示)时,它只覆盖DataGrid.HasItems对象,另一种方式是在Visibility属性上使用Binding,但为了清楚起见,我根据您的问题使用了Trigger。


示例二: 一次性使用TextBlock叠加

这与上面的示例类似,但是您只需将两个控件封装在Grid中,而不是修改DataGrid样式。

虽然这样可行但是这个代码需要复制并粘贴到你想要使用的任何地方,这是不理想的。

代码如下:

    <Grid>
        <DataGrid Name="dg" ItemsSource="{Binding Path=DisplayItems}" />

        <Border HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="{Binding ElementName=dg, Path=HasItems, Converter={StaticResource booleanToVisibilityConverter}}" SnapsToDevicePixels="True" Background="Coral" BorderBrush="DarkRed" BorderThickness="1">
            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="No items to display" Margin="20" />
        </Border>
    </Grid>

原帖:

我不确定您为HasItems使用了什么,但请确保它是一个提升相应PropertyChanged事件的属性。

此代码对我有效:

DataGrid XAML

    <DataGrid Name="dataGrid" RowDetailsVisibilityMode="VisibleWhenSelected">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Path=TextToDisplay}" />
        </DataGrid.Columns>

        <DataGrid.RowDetailsTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Name="txtnoitems" Text="No Records Found" Visibility="Collapsed"></TextBlock>
                </StackPanel>

                <DataTemplate.Triggers>
                    <DataTrigger Binding="{Binding HasItems}" Value="False">
                        <Setter  TargetName="txtnoitems" Property="Visibility" Value="Visible"></Setter>
                    </DataTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </DataGrid.RowDetailsTemplate>
    </DataGrid>

(注意:我还在触发器绑定中删除了{RelativeSource},并将RowDetailsVisibilityMode属性设置为DataGrid)

某些商品类 (用作子商品)

public class SomeItem : INotifyPropertyChanged
{
    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public event PropertyChangedEventHandler PropertyChanged;

    #region HasItems Definition

    private bool _HasItems = true;

    public bool HasItems
    {
        get
        {
            return _HasItems;
        }
        set
        {
            _HasItems = value;
            OnPropertyChanged("HasItems");
        }
    }

    #endregion // end of HasItems region
    #region TextToDisplay Definition

    private string _TextToDisplay = null;

    public string TextToDisplay
    {
        get
        {
            return _TextToDisplay;
        }
        set
        {
            _TextToDisplay = value;
            OnPropertyChanged("TextToDisplay");
        }
    }

    #endregion // end of TextToDisplay region

    public SomeItem(string blah)
    {
        TextToDisplay = blah;
    }
}

<强>用法:

        dataGrid.Items.Add(new SomeItem("items"));
        dataGrid.Items.Add(new SomeItem("items"));
        dataGrid.Items.Add(new SomeItem("not items") { HasItems = false });
        dataGrid.Items.Add(new SomeItem("items"));