0

Firstly, it's worth mentioning that I've looked at other similar topics, and they've helped me get this far but I need a little help getting over the finishing line.

The problem I'm having is that I can't get my DataTrigger to show the correct image, When the InPossesion bool flag is set to false I'm setting my enum property as IconImage2, which in turn should change the image in the datagrid to a red circle, this doesn't happen. If anyone could give me any pointers as to where I'm going wrong that would be great.

ViewModel Enum

 public enum  IconEnum
 {
    IconImage1,
    IconImage2
 }

 public IconEnum MyIconEnumProperty
 {
   get { return _myEnum; }
   set
     {
       _myEnum = value;
        RaisePropertyChanged("MyIconEnumProperty");
     }
  }    

ViewModel Method to load orders

 private void LoadCloakroomOrders()
 {
     CloakroomOrderRepository repo = new CloakroomOrderRepository();
     //Get All orders
     var orders = repo.GetPublic();
     foreach (var orderItem in orders)
      {
          Orders.Add(orderItem);
          if (orderItem.InPossesion == false)
          {
              MyIconEnumProperty = IconEnum.IconImage2;
          }
      }
  }

XAML

<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Orders}" 
                  SelectedItem="{Binding Path=SelectedCloakroomOrder}"
                  Margin="0,23,0,-0.5" Width="980" >
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Image Visibility="{Binding ShowIcon,
                              Converter={StaticResource BooleanToVisibilityConverter},  
                              FallbackValue=hidden}" >
                               <Image.Style>
                                   <Style TargetType="Image">
                                       <Setter Property="Source" Value="/Resources/Images/circle_green.png"/>
                                        <Style.Triggers>
                                            <DataTrigger Binding="{Binding MyIconEnumProperty}" Value="IconImage2">
                                                <Setter Property="Source" Value="/Resources/Images/circle_red.png"></Setter>
                                            </DataTrigger>
                                        </Style.Triggers>
                                    </Style>
                               </Image.Style>
                           </Image>
                        </DataTemplate>
                  </DataGridTemplateColumn.CellTemplate>
              </DataGridTemplateColumn>
           </DataGrid.Columns>
      </DataGrid>

Thanks!

Andrea Antonangeli
  • 1,242
  • 1
  • 21
  • 32
bucky112
  • 74
  • 1
  • 7
  • Please post a question explaining the problem you are having, you have only posted requirements... – eddie_cat Oct 27 '14 at 14:18
  • Don't expose `enum` for the view. View-model can take value of enum (from some business logic) and convert it to image source, which you can use to bind your view image to. – Sinatr Oct 27 '14 at 14:51

2 Answers2

2

Rather than having an enum in the VM, you could simply have an InPossesion property, and hide/show two images based on that. This keeps the view model cleaner, and the XAML clearer:

ViewModel:

public bool InPossession
{
    get { return _inPossession; }
    set { _inPossion = value; RaisePropertyChanged("InPossession"); }
}

private void LoadCloakroomOrders()
{
    CloakroomOrderRepository repo = new CloakroomOrderRepository();
    //Get All orders
    var orders = repo.GetPublic();
    foreach (var orderItem in orders)
    {
        Orders.Add(orderItem);
        if (orderItem.InPossesion == false)
        {
            InPossession = false;
        }
    }
}

Converter:

public class BooleanToVisibilityConverter : IValueConverter
{
    public Visibility VisibilitIfTrue { get;set; }
    public Visibility VisibilitIfFalse { get;set; }

    public BooleanToVisibilityConverter()
    {
        // Set default values for the most common usage
        VisibilityIfTrue = Visible;
        VisibilityIfFalse = Collapsed;
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {

    // Converter could be extended to handle nullable bools as well, but ignore for now
    if (value == null)
    {
        return DependencyProperty.UnsetValue;
    }

    // value should be of type bool
    bool b = (bool)value;
    if (b == true)
    {
        return VisibilityIfTrue;
    }
    else
    {
        return VisibilityIfFalse;
    }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
         throw new NotImplementedException(); // Not necessary
    }
}

XAML:

<UserControl>
    <UserControl.Resources>
        <converters:BooleanToVisibilityConverter x:Key="TrueToVisibleConverter" VisibilityIfTrue="Visible" VisibleIfFalse="Collapsed"/>
        <converters:BooleanToVisibilityConverter x:Key="FalseToVisibleConverter" VisibilityIfTrue="Collapsed" VisibleIfFalse="Visible"/>
    </UserControl.Resources>
</UserControl>
...
<DataTemplate>
    <Grid Visibility="{Binding ShowIcon, FallbackValue=hidden}">
         <Image Source="/Resources/Images/circle_green.png" Visibility="{Binding InPossession, Converter={StaticResource TrueToVisibleConverter}}"/>
         <Image Source="/Resources/Images/circle_red.png" Visibility="{Binding InPossession, Converter={StaticResource FalseToVisibleConverter}}"/>
    </Grid>
</DataTemplate>
sondergard
  • 3,184
  • 1
  • 16
  • 25
  • Thanks for this, although I haven't quite got it sorted its the push I needed. – bucky112 Oct 27 '14 at 15:00
  • I added code to illustrate my idea about the true/false visibility converter – sondergard Oct 27 '14 at 15:19
  • I'm having trouble implementing the new properties into converter logic I'm looking @ http://stackoverflow.com/questions/534575/how-do-i-invert-booleantovisibilityconverter but haven't had much luck, could you provide a example? – bucky112 Oct 27 '14 at 15:45
  • I added full logic of the converter, and put the XAML and VM parts together - does it make sense? – sondergard Oct 27 '14 at 16:15
  • Yes, that makes sense. I'll put it all together and let you know how I get on, thank you. – bucky112 Oct 27 '14 at 16:39
  • It would seem the icon always appears as false, I set the private _inPossesion bool to true as default then like you say set it as false if needed in the private method. Doesn't seem to make any difference. – bucky112 Oct 27 '14 at 16:59
  • Have you remembered to set the DataContext property of the view? – sondergard Oct 28 '14 at 08:06
  • Yes, I'm setting it in my xaml: DataContext="{Binding EntryViewModel, Source={StaticResource Locator}}"> – bucky112 Oct 28 '14 at 08:46
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/63755/discussion-between-sondergard-and-bucky112). – sondergard Oct 28 '14 at 09:05
1

Try also specify the enum type.

Value="{x:Static wpf:IconEnum.IconImage2}"

wpf: is a namespace like xmlns:wpf="clr-namespace:Sandbox.WPF" in my case. But I would probably go for another solution, like sondergard suggests, it's much cleaner style than this hacking.

Ondrej Janacek
  • 12,486
  • 14
  • 59
  • 93