How can you get a value from a variable in ItemsSource in a custom DataTemplate?

I have these objects as item in ItemSource.

public class Chat
{
    public ENUM_CHAT_OWNER ENUM_CHAT_OWNER_ { get; set; }
    public string string_Message { get; set; }
    public string string_Name { get; set; }
    public Chat
    (
        ENUM_CHAT_OWNER _ENUM_CHAT_OWNER_,
        string _string_Message,
        string _string_Name    
    )
    {
        ENUM_CHAT_OWNER_ = _ENUM_CHAT_OWNER_;
        string_Message = _string_Message;
        string_Name = _string_Name;
    }
}

This is my custom DataTemplate.

DataTemplate DataTemplate_StackLayout_Chat = new DataTemplate
(
    () =>
    {
        BoxView BoxView_PhotoPrototype = new BoxView()
        {
            HeightRequest = 40,
            WidthRequest = 40,
        };
        Label Label_Message = new Label()
        {

        };
        Label Label_Name = new Label()
        {

        };
        StackLayout StackLayout_Chat = new StackLayout() { };
        StackLayout StackLayout_Label = new StackLayout()
        {
            Children = { Label_Name, Label_Message },
            Orientation = StackOrientation.Vertical,
        };
        StackLayout_Chat.Children.Add(BoxView_PhotoPrototype);
        StackLayout_Chat.Children.Add(StackLayout_Label);
        StackLayout_Chat.Orientation = StackOrientation.Horizontal;

        //Set bindings.
        Label_Message.SetBinding(Label.TextProperty, "string_Message");
        Label_Name.SetBinding(Label.TextProperty, "string_Name");

        return new ViewCell() { View = StackLayout_Chat };
    }
)
{ };

I want to get access of ENUM_CHAT_OWNER_ from my DataTemplate DataTemplate_StackLayout_Chat . How can I achieve this?

Answers

  • ShawnCastrianni.5092ShawnCastrianni.5092 US ✭✭✭
    edited July 2016

    If I understand what you are asking, the answer is you don't get access to it. The DataTemplate is a template and it is used at runtime to control how each row in your ListView (or whatever your are using) is displayed. The bindings you have setup are used to extract out the properties your want from each Chat object as they are bound to each row. Your current bindings allow you access to Message and Name, so what is different that you want to do with the OWNER property?

    Maybe it would help me understand if I knew what you wanted to do with the OWNER property. Why not just make another Label in your template and bind that Label to the OWNER property?

  • MikaelKristyawicaksonoMikaelKristyawicaksono USMember ✭✭
    edited July 2016

    @ShawnCastrianni.5092
    Hmmm, what I want is actually to position a BoxView.
    So if the OWNER = SELF then the BoxView will be displayed on left.
    If the OWNER = OTHER then the BoxView will be displayed on the right.

    Is there any non - View based object that can be binded with a value? Like a Label.Text but without any visual element and just solely for containing a value.

  • yes, you can make your own BindableProperty in the data template and then bind to it from outside the data template. so from outside you can call DataTemplate_StackLayout_Chat.SetBinding(YOUR CUSTOM BINDABLE PROPERTY, "ENUM_CHAT_OWNER_");

    however, I think it would be easier a different way. I would make your data template with 2 BoxViews. one is on the left and the other is on the right. then alongside your bindings for name and message, bind the IsVisible property on those BoxViews to the ENUM_CHAT_OWNER_ using a value converter for both. th value converter would convert the value of ENUM_CHAT_OWNER_ to a Boolean to be applied to the IsVisible property of the BoxView. but you use 2 different value converters. one value converter returns true for SELF and the other value converter returns true for OTHER. that way only one of the BoxViews will be visible at one time.

  • ShawnCastrianni.5092ShawnCastrianni.5092 US ✭✭✭
    edited July 2016

    Or yet another way, is to have just the one BoxView inside a vertical StackLayout inside your DataTemplate. You have this already. So to make the BoxView be left or right, you would need to change the HorizontalOptions of the BoxView. If the HorizontalOptions is set to LayoutOptions.Start, it should be on the left. If HorizontalOptions is set to LayoutOptions.End, it should be on the right. Luckily, HorizontalOptions is a bindable property for any View, like BoxView. So you simply add:

    BoxView_PhotoPrototype.SetBinding(BoxView.HorizontalOptionsProperty,"ENUM_CHAT_OWNER_",converter: new EnumChatToLayoutOptionsValueConverter());
    

    Then you write the EnumChatToLayoutOptionsValueConverter converter so that it returns a LayoutOptions.Start if the Owner is SELF and LayoutOptions.End if the Owner is OTHER.

  • @ShawnCastrianni.5092

    It kinda work.

    https://s31.postimg.org/3qk14aafv/Screenshot_2016_07_01_12_30_34.png

    But the other BoxView is not in the right side of the screen.

    Here are my codes.

    DataTemplate DataTemplate_StackLayout_Chat = new DataTemplate
    (
        () =>
        {
            BoxView BoxView_PhotoPrototype = new BoxView()
            {
                Color = Color.Red,
                HeightRequest = 40,
                WidthRequest = 40,
            };
            Label Label_Container_Owner = new Label()
            {
    
            };
            Label Label_Message = new Label()
            {
    
            };
            Label Label_Name = new Label()
            {
    
            };
            StackLayout StackLayout_Chat = new StackLayout() { };
            StackLayout StackLayout_Label = new StackLayout()
            {
                Children = { Label_Name, Label_Message },
                Orientation = StackOrientation.Vertical,
            };
            StackLayout_Chat.Children.Add(BoxView_PhotoPrototype);
            StackLayout_Chat.Children.Add(StackLayout_Label);
            StackLayout_Chat.Orientation = StackOrientation.Horizontal;
    
            //Set bindings.
            BoxView_PhotoPrototype.SetBinding
            (
                BoxView.HorizontalOptionsProperty,
                "ENUM_CHAT_OWNER_",
                converter: new Converter_ENUM_CHAT_OWNER_To_LayoutOptions()
            );
            Label_Message.SetBinding(Label.TextProperty, "string_Message");
            Label_Name.SetBinding(Label.TextProperty, "string_Name");
    
            return new ViewCell() { View = StackLayout_Chat };
        }
    )
    { };
    

    And these.

    public class Converter_ENUM_CHAT_OWNER_To_LayoutOptions : IValueConverter
    {
        object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value.ToString() == "OTHER")
            {
                return LayoutOptions.End;
            }
            else if (value.ToString() == "SELF")
            {
                return LayoutOptions.Start;
            }
            else
            {
                return null;
            }
        }
    
        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    
  • seeing a picture of your cell helps me. due to the way you have your cell laid out, simply changing the horizontal options through binding won't work. therefore, you can try the 2 BoxView approach I described. make your cell have 2 BoxViews, one on left and one on right. then bind each BoxView IsVisible property to the ENUM with 2 different value converters. one that returns true on SELF and one that returns true on OTHER.

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    HorizontallyOptions is only an alignment. StackLayout follows the order you "Add" items.
    You should have 2 RedBox, one on the start and one of the end of StackLayout. Then Bind the IsVisible Property. The Right should be have a IValueConverter that convert the boolean value (so when the boolean property is true for the Box on the left, it's become false with the IValueConverter for the box on the right).

    michaelridland.com/xamarin/freshessentials-for-xamarin-forms-the-must-have-nuget-for-forms/

    you can find a InverseBooleanConverter

Sign In or Register to comment.