Проблема привязки при использовании DataTrigger в WPF - PullRequest
1 голос
/ 25 августа 2011

У меня проблема с привязками в моем проекте 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>

Я пытаюсь сделать так, чтобы TextBlock появилось, когда DataGrid.HasItems равно false. По какой-то причине это не работает.

Кто-нибудь может понять, в чем может быть моя проблема?

1 Ответ

1 голос
/ 25 августа 2011

Редактировать в соответствии с предположением в комментариях:

Если, как упомянул @bathineni, вы хотите отобразить прямоугольник над DataGrid, когда в коллекции нет элементов, вы, вероятно, вероятно,Мне нужно использовать механизм, отличный от RowDetailsTemplate, чтобы добиться этого.

Два примера, о которых я могу подумать, - это стилизация DataGrid, чтобы он содержал выделенный TextBlock для отображения этого сообщения, а другой -создать сетку, которая содержала бы DataGrid и сообщение, которое вы хотели бы отобразить сверху.

Пример первый: Стиль DataGrid

Вы можетенайдите очень хороший учебник здесь , который покажет вам, как стилизовать внутренности DataGrid, аналогично тому, как это делает Самуэль, всего их четыре.

В шаблоне 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", когда DataGrid.HasItems имеет значение false (отображается с помощью триггера), другим способом будет использование привязки к свойству Visibility, но радиЯ использовал триггер в соответствии с вашим вопросом.

Пример два: Одноразовое наложение TextBlock

Это будет похоже на приведенный выше пример, но вместо изменения стиля 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"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...