AvaloniaUI / Avalonia.Xaml.Behaviors

Port of Windows UWP Xaml Behaviors for Avalonia Xaml.
MIT License
385 stars 46 forks source link

DataTriggerBehavior doesn't work with DataGridRow style #153

Open ds1709 opened 5 months ago

ds1709 commented 5 months ago

I have a minimal test case, where I can't make DataTriggerBehavior make to work with DataGridRow style. I have simple view models:

    public sealed class MyViewModelList
    {
        public List<MyViewModel> Items { get; } = new List<MyViewModel>();
    }

    public sealed class MyViewModel : INotifyPropertyChanged
    {
        private Guid id;

        public Guid Id => id;

        public bool IsEven => id.ToByteArray()[15] % 2 is 0;

        public event PropertyChangedEventHandler? PropertyChanged;

        public void UpdateId()
        {
            id = Guid.NewGuid();
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Id)));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsEven)));
        }
    }

and a simple view for it:

    <DataGrid ItemsSource="{Binding Items}">
      <DataGrid.Styles>
        <Style Selector="DataGridRow">
          <Setter Property="Foreground" Value="Blue" />
          <Setter Property="i:Interaction.Behaviors">
            <Setter.Value>
              <i:BehaviorCollectionTemplate>
                <i:BehaviorCollection>
                  <ia:DataTriggerBehavior Binding="{Binding IsEven}" ComparisonCondition="Equal" Value="True">
                    <ia:ChangePropertyAction PropertyName="Foreground" Value="Red" />
                  </ia:DataTriggerBehavior>
                  <ia:DataTriggerBehavior Binding="{Binding IsEven}" ComparisonCondition="Equal" Value="False">
                    <ia:ChangePropertyAction PropertyName="Foreground" Value="Green" />
                  </ia:DataTriggerBehavior>
                </i:BehaviorCollection>
              </i:BehaviorCollectionTemplate>
            </Setter.Value>
          </Setter>
        </Style>
      </DataGrid.Styles>
      <DataGrid.Columns>
        <DataGridTextColumn Header="VM" Binding="{Binding}" />
        <DataGridTextColumn Header="Name" Binding="{Binding Id}" />
      </DataGrid.Columns>
    </DataGrid>

As you can see, by default, row foreground is Blue. When Id is changed, row foreground must be changed to Red or Green. First of all, it's not compilled with error Unable to resolve property or method of name 'IsEven' on type 'AvaloniaApplication1.MyViewModelList'. Second, if I use cast in binding like this Binding="{Binding (vm:MyViewModel).IsEven}", it compiles successfuly, but color doesnt't canges. Same for DataGridCell style. Is it bug or I do somthing wrong?

maxkatz6 commented 4 months ago

Have you tried simpler x:DataType="vm:MyViewModel" ?

yll690 commented 1 month ago

Hi, @maxkatz6 . Sorry to bother you but I have the same issue . And I found it affects all ItemsControl.

For example, add a behavior to Avalonia.Xaml.Behaviors\samples\BehaviorsTestApplication\Views\Pages\EditableListBoxView.axaml (See full code bellow). It will show an error Avalonia error AVLN:0004: Unable to resolve property or method of name 'Name' on type 'BehaviorsTestApplication.ViewModels.MainWindowViewModel'..

It indicates the datacontext of the Binding in the DataTriggerBehavior is the datacontext of MainWindow(MainWindowViewModel), not the datacontext of the ListBoxItem(ItemViewModel). There should be something wrong. You mentioned x:DataType but I don't know how to use it in this situation. Could you add more details?

<UserControl x:Class="BehaviorsTestApplication.Views.Pages.EditableListBoxView"
             xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:vm="using:BehaviorsTestApplication.ViewModels"
             xmlns:views="clr-namespace:BehaviorsTestApplication.Views"
             x:CompileBindings="True" x:DataType="vm:MainWindowViewModel"
             mc:Ignorable="d" d:DesignWidth="600" d:DesignHeight="450">
  <Design.DataContext>
    <vm:MainWindowViewModel />
  </Design.DataContext>
  <ListBox ItemsSource="{Binding Items}">
    <ListBox.Styles>
      <Style Selector="ListBoxItem">
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <Setter Property="Margin" Value="0" />
        <Setter Property="Padding" Value="0" />
        <Setter Property="Interaction.Behaviors">
          <Setter.Value>
            <BehaviorCollectionTemplate>
              <BehaviorCollection>
                <DataTriggerBehavior Binding="{Binding Name}" Value="Third Item">
                  <ChangePropertyAction PropertyName="Foreground" Value="Red" />
                </DataTriggerBehavior>
              </BehaviorCollection>
            </BehaviorCollectionTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </ListBox.Styles>
    <ListBox.ItemTemplate>
      <DataTemplate DataType="vm:ItemViewModel" x:CompileBindings="False">
        <views:ItemView />
      </DataTemplate>
    </ListBox.ItemTemplate>
  </ListBox>
</UserControl>