0

I have a ListView with an ComboBox in its ItemTemplate. The ComboBox is also bound to the same list as of the ListView with a Converter. The ComboBox is populated properly but the SelectedItem doesn't show up.

I have tried overriding the Equals method of the underlying object too.

XAML:

<ListView x:Name="FactorsListView"
    ItemsSource="{Binding FactorList}" SelectedItem="{Binding SelectedFactor, Mode=OneWayToSource}"
    ScrollViewer.CanContentScroll="False">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid d:DesignWidth="461.333" d:DesignHeight="368.96">
                <StackPanel>
                    <Grid Height="30.96" Visibility="{Binding IsChecked, ElementName=Monetary, Converter={StaticResource BoolToVis}}">
                        <Label Content="Related Quantitative Factor:" HorizontalAlignment="Left" Margin="10,0,0,0" VerticalAlignment="Top"/>
                        <ComboBox Margin="171.707,4,10,0" VerticalAlignment="Top" Width="Auto" ItemsSource="{Binding DataContext.FactorList, ElementName=UcGrid, Converter={StaticResource QtyFacConverter}}" SelectedItem="{Binding RelatedQuantityFactor}" DisplayMemberPath="Name"/>
                    </Grid>
                </StackPanel>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>
<ListView>

Converter:

public class FactorConverters : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        ObservableCollection<Factor> givenList = value as ObservableCollection<Factor>;
        ObservableCollection<Factor> rList = new ObservableCollection<Factor>();
        if (givenList != null)
        {
            foreach(Factor factor in givenList)
            {
                if (!factor.IsMonetary)
                {
                    rList.Add(factor);
                }
            }
        }
        return rList;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value;
    }
}

Factor Class:

public class Factor : ModelBase
{
    private Factor _RelatedQuantityFactor;

    public Factor RelatedQuantityFactor
    {
        get
        {
            return _RelatedQuantityFactor;
        }
        set
        {
            if (_RelatedQuantityFactor != value)
            {
                _RelatedQuantityFactor = value;
                RaisePropertyChanged("RelatedQuantityFactor");
            }
        }
    }

    public override bool Equals(object obj)
    {
        if (obj == null || !(obj is Factor))
        {
            return false;
        }
        else
        {
            bool res = ((Factor)obj).ID == this.ID;
            return res;
        }
    }
}

FactorsViewModel class:

public class FactorsViewModel : ViewModelBase
{
    private ObservableCollection<Factor> _FactorList;
    private RevenueItem _SelectedRevenueItem;
    private ObservableCollection<Factor> _UniversalFactors;
    private Factor _SelectedFactor;
    private ObservableCollection<Factor> _QuantitativeFactorHelperList;

    public ObservableCollection<Factor> FactorList
    {
        get
        {
            return _FactorList;
        }
        set
        {
            if (_FactorList != value)
            {
                _FactorList = value;
                AttachFactorListner(value);
            }
        }
    }

    private void AttachFactorListner(ObservableCollection<Factor> value)
    {
        foreach (Factor factor in value)
        {
            factor.PropertyChanged += factor_PropertyChanged;
        }
        RaisePropertyChanged("FactorList");
    }

    void factor_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "IsMonetary")
        {
            RaisePropertyChanged("FactorList");
        }
    }


    public RevenueItem SelectedRevenueItem
    {
        get
        {
            return _SelectedRevenueItem;
        }
        set
        {
            if (_SelectedRevenueItem != value)
            {
                _SelectedRevenueItem = value;
                RaisePropertyChanged("SelectedRevenueItem");
            }
        }
    }
    public ObservableCollection<Factor> UniversalFactors
    {
        get
        {
            return _UniversalFactors;
        }
        set
        {
            if (_UniversalFactors != value)
            {
                _UniversalFactors = value;
                RaisePropertyChanged("UniversalFactors");
            }
        }
    }
    public Factor SelectedFactor
    {
        get
        {
            return _SelectedFactor;
        }
        set
        {
            if (_SelectedFactor != value)
            {
                _SelectedFactor = value;
                RaisePropertyChanged("SelectedFactor");
            }
        }
    }
    public ObservableCollection<Factor> QuantitativeFactorHelperList
    {
        get
        {
            return _QuantitativeFactorHelperList;
        }
        set
        {
            if (_QuantitativeFactorHelperList != value)
            {
                _QuantitativeFactorHelperList = value;
                RaisePropertyChanged("QuantitativeFactorHelperList");
            }
        }
    }

    public FactorsViewModel(RevenueItem revenueItem)
    {
        _SelectedRevenueItem = revenueItem;
        _FactorList = revenueItem.Factors;
        AttachFactorListner(_FactorList);

    }


}

The View and Viewmodels: PostImg Link

eskawl
  • 587
  • 1
  • 4
  • 17
  • Where is the "FactorList" property ? – Bakri Bitar Jul 16 '15 at 02:07
  • It is on the viewmodel of Usercontrol which hosts the listview – eskawl Jul 16 '15 at 02:14
  • public class FactorsViewModel : ViewModelBase { private ObservableCollection _FactorList; public ObservableCollection FactorList { get { return _FactorList; } set { if (_FactorList != value) { _FactorList = value; AttachFactorListner(value); } } } – eskawl Jul 16 '15 at 02:15

3 Answers3

0

You should bind SelectedItem to Some Property in the ViewModel

As I saw in your code you bound it to the Property RelatedQuantityFactor from your model Factor not from ViewModel

Bakri Bitar
  • 1,543
  • 18
  • 29
0

Let's see MVVM pattern. enter image description here

ViewModel should inherit from InotifyPropertyChanged so that it can update View. Model is Object which include Property and Behavior,but it doesn't communicate with View

So,if you wang to update your UI ,you should use Data Binding. I think Factor is ViewModel.

public class Factor: ModelBase
{
    private ItemViewModel _selectedFactor;
    Public ItemViewModel SelectedFactor
     {
        get
        {
           return _selectedFactor;
        }
        set
        {
         _selectedFactor = value;
          RaisePropertyChanged("RelatedQuantityFactor");
        }
     }
}

you also should change the Binding Mode.

SelectedItem="{Binding SelectedFactor, Mode=OneWay}"

Finally, don't forget to assign DataContext

FactorsListView.DataContext = new Factor();
zhangyiying
  • 414
  • 4
  • 15
0

Just some question:

  1. Do the viewmodel contain any variable name "RelatedQuantityFactor"?

Try to post your code behind which include d initialization of data context and viewmodel if you still face any problem .

Update : You can try to put breakpoint into your setter and getter of RelatedQuantityFactor to investigate whether it update your relatedquantityfactor as you expected

Update 2: See this Difference between SelectedItem, SelectedValue and SelectedValuePath.

Hope its helps :)

Community
  • 1
  • 1
pengMiao
  • 324
  • 1
  • 6
  • 1. No the viewmodel doesn't contain any variable named RelatedQuantityFactor. 2. Yes the selected item is on the factor class. If this is wrong, How should i implement the relation between factor and its relative factor by storing the relative factor in the viewmodel? – eskawl Jul 16 '15 at 03:43
  • @eskawl ooaps sorry i mistaken the relationship, please wait awhile i am updating my answer. – pengMiao Jul 16 '15 at 03:49
  • The binding doesn't point to viewmodel. even if it had, i'd have got an binding error not found in the output during runtime, but there isn't any. – eskawl Jul 16 '15 at 04:03
  • Sorry for the confusion, but the selected item doesn't appear on load. Changing the binding mode of the parent listview had no effect. – eskawl Jul 16 '15 at 06:28
  • @eskawl selectedItem doesn't appear on load... does it means the default select value doesn't appear? – pengMiao Jul 16 '15 at 07:31
  • not the default but the actual related factor doesn't appera – eskawl Jul 16 '15 at 08:05
  • @eskawl have you tried put a breakpoint in the set and get of relatedQuantityFactor? does it enter the set and get when you select a value? – pengMiao Jul 16 '15 at 08:12
  • Yes it enters the get – eskawl Jul 16 '15 at 14:23
  • I read somewhere that the selectedItem is getting set before the items are populated. So how should I deal with this. – eskawl Jul 17 '15 at 14:47