How to change the view of toggle buttons based on a Binding in WPF Datagrid

Asked

Viewed 25 times

2

Hello, I am new with XAML/WPF and I have the following problem. I have a DataGrid which receives as Itemssource a ObservableCollection<DataEstoque>() thus

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 as such:

<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 carried the ObservableCollection<DataEstoque> i can, based on the convert I did or did not show the buttons but it does not work. The convert was made 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 sent object and, based on the references it returns Visible or null. If returned null, it will use the FallbackValue. The problem is, I can’t do the automatic treatment for each line on the datagrid, and it’s not smart to loop and force the visualization of one or another datagrid button.

Does anyone know how to solve?

1 answer

0

I solved my problem by fixing my converter... the problem was that in the validation of the object type I did not compare the same correctly. I also added an "inverter" to the result, in case I want 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();
}

About the methods object.TryCast<T>() and the bool?.toBool(), I have an extensive class containing 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;
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.