Dev
Dev

Reputation: 1826

How to show the selected item of a WPF binding

C#:

public void SetCompetition(Window wT1)
{
    //Add all the Copetition
    wT1._competition = new List<Competition>();
    wT1._competition.Add(new Competition { Logo = "3.png", Name = "test1", IsSelected = false });
    wT1._competition.Add(new Competition { Logo = "3.png", Name = "test2", IsSelected = false });
    wT1._competition.Add(new Competition { Logo = "3.png", Name = "test3", IsSelected = false });
    wT1._competition.Add(new Competition { Logo = "3.png", Name = "test4", IsSelected = false });

        wT1.cboSetupCompetition.ItemsSource = wT1._competition;
        wT1.cboSetupCompetition.Items.Refresh();
    }

Data Template:

<UserControl.Resources>
    <System:Double x:Key="Double1">11</System:Double>
    <DataTemplate x:Key="cmbCompetition">
        <WrapPanel  Height="30" >

            <Label Content="{Binding Name}" ></Label>

        </WrapPanel>
    </DataTemplate>

</UserControl.Resources>

<ComboBox x:Name="cboSetupCompetition" ItemTemplate="{DynamicResource     cmbCompetition}" HorizontalAlignment="Left" Margin="29,28,0,0" VerticalAlignment="Top" Width="173" RenderTransformOrigin="0.5,0.591" FontSize="12" Height="22" IsEditable="True"  Background="#FFD8D8D8" SelectionChanged="UpdateCompetitionSelection"/>

I have a Combobox with a label and an image and when I select an item I would like to see the same format in the Combobox when it is closed. I am not getting any errors I am seeing the name of the application.Competition(this is my object Model) instead of the values of the image and label.

The SetCopetition is invoked when the application loads.

Upvotes: 2

Views: 1441

Answers (2)

MikeT
MikeT

Reputation: 5500

the specific problem as Mn8 spotted is that IsEditable=true forces the combo to display a textbox as the selected item

However you are still thinking winforms not WPF, using code behind to link data into the view causes many problems and instability as quite often this breaks the binding connections which is what is suspected was your problem initially, using a proper MVVM approach will eliminate all these problems

the best overveiw of MVVM i know of is

https://msdn.microsoft.com/en-gb/library/hh848246.aspx

Model

this is your data layer, it handle storage and access to data, your model will handle access to files, databases, services, etc

a simple model would be

public class Model
{
    public string Text { get; set; }
    public Uri Uri { get; set; }
}

ViewModel

on top of your Model you have your View Model this manages the interaction of your View with the model for example here because it uses Prism's BindableBase the SetProperty method notifies the View of any changes to the data, the ObservableCollection automatically notifies of changes to the collection, it also uses Prism's DelegateCommand to allow method binding in the view

public class ViewModel:BindableBase
{
    public ViewModel()
    {
        AddItem = new DelegateCommand(() => Collection.Add(new Model()
        {
            Text = NewText,
            Uri = new Uri(NewUri)
        }));
    }
    private string _NewText;

    public string NewText
    {
        get { return _NewText; }
        set { SetProperty(ref _NewText, value); }
    }
    private string _NewUri;

    public string NewUri
    {
        get { return _NewUri; }
        set { SetProperty(ref _NewUri, value); }
    }

    private Model _SelectedItem;

    public Model SelectedItem
    {
        get { return _SelectedItem; }
        set
        {
            if (SetProperty(ref _SelectedItem, value))
            {
                NewText = value?.Text;
                NewUri = value?.Uri.ToString();
            }
        }
    }

    public ObservableCollection<Model> Collection { get; } = new ObservableCollection<Model>();

    public DelegateCommand AddItem { get; set; }
}

View

the View ideally does nothing but displays and collects data, all formatting / Styling should be done here

firstly you need to define the data source, the usual way is via the data context as this auto inherits down the visual tree, in the example because i set the window's datacontext, i have also set it for everything in the window the only exception is the dataTempplate as this is set to the current item in the collection

i then bind properties to the datasource

Note the code behind file is only the default constructor no other code at all

<Window 
    x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:ViewModel/>
    </Window.DataContext>
    <StackPanel>
        <GroupBox Header="Text">
            <TextBox Text="{Binding NewText}"/>
        </GroupBox>
        <GroupBox Header="URI">
            <TextBox Text="{Binding NewUri}"/>
        </GroupBox>
        <Button Content="Add" Command="{Binding AddItem}"/>
        <ComboBox ItemsSource="{Binding Collection}" SelectedItem="{Binding SelectedItem}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image Source="{Binding Uri}" />
                        <TextBlock Text="{Binding Text}"/>
                    </StackPanel>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>

    </StackPanel>
</Window>

Upvotes: 1

mm8
mm8

Reputation: 169200

A TextBox is not able to display a Label and an Image or whatever elements that are in your DataTemplate in it.

Set the IsEditable property of the ComboBox to false and it should work as expected, i.e. your DataTemplate will be applied to the selected item when the ComboBox is closed:

<ComboBox x:Name="cboSetupCompetition" IsEditable="False"  ItemTemplate="{DynamicResource cmbCompetition}" HorizontalAlignment="Left" Margin="29,28,0,0" VerticalAlignment="Top" Width="173" RenderTransformOrigin="0.5,0.591" FontSize="12" Height="22" Background="#FFD8D8D8" SelectionChanged="UpdateCompetitionSelection"/>

Your issue has nothing to do with MVVM...

Upvotes: 1

Related Questions