How to change the display of alternate buttons based on a binding in the DataGrid in WPF

2

Hello, I'm new to XAML / WPF and I have the following problem. I have a DataGrid that receives as ItemsSource a ObservableCollection<DataEstoque>() so

public class DataEstoque
{
    public string Id { get; set; }
    public string Descricao { get; set; }
    public int WebCodigo { get; set; }
}

In the view, my DataGrid is declared like this:

<DataGrid x:Name="DataGridProdutos" AutoGenerateColumns="False" ColumnWidth="Auto" 
          Margin="10" Background="White" IsReadOnly="True">
  <DataGrid.Columns>
    <DataGridTextColumn Header="Id" Binding="{Binding Id}" Width="75" 
                        SortDirection="Ascending"/>
    <DataGridTextColumn Header="Descrição do produto" Width="*" 
                        Binding="{Binding Descricao}" />
    <DataGridTemplateColumn Width="auto">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <DockPanel Margin="0, -3, 0, -3">
            <Button Click="VincularProduto" DockPanel.Dock="Left" Foreground="Green"
                    Style="{DynamicResource BtnLink}" Content="vincular"
                    Width="60" Height="24" Tag="{Binding Id}"
                    Visibility="{Binding WebCodigo, Source=WebCodigo,
                                 Converter={StaticResource VisibleConverter}, 
                                 ConverterParameter=WebCodigo, 
                                 FallbackValue=Visible}"/>
            <Button Click="AtualizarProduto" DockPanel.Dock="Left" Foreground="Blue"
                    Style="{DynamicResource BtnLink}" Content="atualizar" 
                    Width="60" Height="20"  Tag="{Binding Id}"
                    Visibility="{Binding WebCodigo, Source=WebCodigo,
                                 Converter={StaticResource VisibleConverter}, 
                                 ConverterParameter=WebCodigo,
                                 FallbackValue=Collapsed}"/>
                        </DockPanel>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

The intention is that when I load ObservableCollection<DataEstoque> I can, based on the conversion I did show the buttons or not but it does not work. The convert was done like this:

public class VisibleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
                          CultureInfo culture)
    {
        if ((value is string && string.IsNullOrEmpty((string)value)) ||
            (value is bool && !!(bool)value) ||
            (value is int && ((int)value) > 0) ||
            (value != null))
            return Visibility.Visible;

        return null;
    }

    public object ConvertBack(object value, Type targetType, 
                              object parameter, CultureInfo culture) =>
        throw new NotImplementedException();
}

The converter code has already been tested, it checks the type of the object being sent, and based on the references it returns Visible or null. If null is returned, it will use FallbackValue . The problem is that I can not do the automatic processing for each row in the datagrid, and it is not smart to loop and force the display of one or the other button in the datagrid.

Does anyone know how to solve it?

    
asked by anonymous 30.07.2018 / 13:54

1 answer

0

I solved my problem by correcting my convert ... the problem was that in validating the object type I did not compare it correctly. I also added an "inverter" to the result if I wanted to deny the result of the comparison. So:

public class VisibleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        parameter.TryCast(out bool? invert);
        if (parameter is string && parameter.ToString().ToLower() == "false")
            invert = false;

        bool test = false;

        if (value.TryCast(out string stringValue))
            test = !string.IsNullOrEmpty(stringValue.Trim());
        else if (value.TryCast(out int intValue))
            test = intValue > 0;
        else if (value.TryCast(out bool boolValue))
            test = boolValue;
        else
            test = value != null;

        if (invert != null && !invert.toBool()) test = !test;

        if (test) return Visibility.Visible;

        return null;
    }
    public object ConvertBack(object value, Type targetType, object parameter, 
                              CultureInfo culture) =>
         throw new NotImplementedException();
}

On methods object.TryCast<T>() and bool?.toBool() , I have an extensive class that contains the 2 methods:

public static class MyExtensions
{
    public static bool toBool(this bool? value) => 
        value != null && value != false;
    public static bool TryCast<T>(this object obj, out T result)
    {
        if (obj is T)
        {
            result = (T)obj;
            return true;
        }

        result = default(T);
        return false;
    }
}
    
30.07.2018 / 15:25