-2

So, I'm at a lost, and hope for some guidance. I'm using MVVM pattern and EF.

My View contains a datagrid bound to a observable collection within the view model. The UI has furthermore 3 comboboxes with possible data to minimize the data shown.

So I've been googling around and found nothing I could use (or might not have understood it correctly).

How do I search and select the items from a ObservableCollection, and update the datagrid accordingly?

    public ObservableCollection<DimTargets> TargetParameters { get; set; }
    private void SelectionChanged(object obj)
    {
        if (obj is FactTargets)
        {
            SelectedFactTarget = (FactTargets)obj;
        }
        else if (obj is DimLocation)
        {
            SelectedLocation = (DimLocation)obj;
            ViewCollection.Select(x => x.Location == SelectedLocation.Location);
            TargetParameters.Where(x => x.FactTargets == SelectedLocation.FactTargets);
        }
        else //DimBladeType
        {
            SelectedBladeType = (DimBladeType)obj;
            int[] a = DimTargetsController.ReturnBladeType(SelectedBladeType);
            foreach (int i in a)
            {
                TargetParameters.Single(k => k.ID == i);
            }
            var os = TargetParameters.Where(d => d.ID == );
            TargetParameters = Convert<DimTargets>(os);
            //TargetParameters.Where(ka => ka.ID == a);
            //TargetParameters = new ObservableCollection<DimTargets>(TargetParameters.Where(t => t.FactTargets == SelectedBladeType.FactTargets));
            //var obs = TargetParameters.Where(t => t.FactTargets == SelectedBladeType.FactTargets);
            //TargetParameters = Convert<DimTargets>(obs);
            //ViewCollection.Select(x => x.BladeType == SelectedBladeType.BladeType).ToList();
        }
    }

    public ObservableCollection<T> Convert<T>(IEnumerable original)
    {
        return new ObservableCollection<T>(original.Cast<T>());
    }

XAML:

 ComboBox ItemsSource="{Binding FactTargetCollection, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedFactTarget}" DisplayMemberPath="FYQuater" Behaivor:SelectionChangedBehaviour.Command="{Binding SelectionChangedCommand}"/>
            <ComboBox ItemsSource="{Binding LocationCollection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedLocation}" DisplayMemberPath="Location" Behaivor:SelectionChangedBehaviour.Command="{Binding SelectionChangedCommand}"/>
            <ComboBox ItemsSource="{Binding BladeTypeCollection, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding SelectedBladeType}" DisplayMemberPath="BladeType" Behaivor:SelectionChangedBehaviour.Command="{Binding SelectionChangedCommand}"/>

            <Button Content="Submit" Style="{StaticResource BaseButtonStyle}"></Button>
        </StackPanel>

        <StackPanel x:Name="WorkPanel" DockPanel.Dock="Right">
            <DataGrid ItemsSource="{Binding TargetParameters}">

            </DataGrid>
        </StackPanel>`

Hope this gives a better idea of what i'm trying to do. the c# code are filled with examples with what i've tried.

Sinnich
  • 342
  • 5
  • 17
  • 2
    Please post your code – Eldho Apr 11 '16 at 13:33
  • Are you asking how to select rows in the datagrid based on a property of your viewmodel? [This may help](http://stackoverflow.com/a/4902454/424129) (`Selector` is a base class of `DataGrid`, so `DataGrid` has a `SelectedItem` property just like `ComboBox` etc.). `DataGrid.SelectionMode`, `DataGrid.SelectionUnit`, and `DataGrid.SelectedCells` may be helpful as well. – 15ee8f99-57ff-4f92-890c-b56153 Apr 11 '16 at 13:34
  • 1
    You're assigning a new value to `TargetParameters` without notifying the UI. You need to fire your `PropertyChanged` event in the settter for `TargetParameters`. What purpose does the `Convert` method serve anyway? What is the purpose of `TargetParameters.Single(k => k.ID == i);`? That call does nothing. `TargetParameters.Where(x => x.FactTargets == SelectedLocation.FactTargets);` also does nothing. Do you fire `PropertyChanged` in the setter for `SelectedLocation`? If you have no `PropertyChanged` event, your viewmodel needs to implement `INotifyPropertyChanged`. – 15ee8f99-57ff-4f92-890c-b56153 Apr 11 '16 at 14:02
  • Looks like you tried replacing the collection. Nope. It's easy enough to find an item in the collection. Once you have the item, you can find its index. You can then remove that item and replace it with an updated item from the database. Manipulate the collection object, don't replace the entire collection. –  Apr 11 '16 at 17:05
  • I suggest that you use a CollectionViewSource that wraps you ObservableCollection. Take a look at Hanselman's tutorial about it http://www.hanselman.com/blog/CollectionViewSourceIsCrazyUsefulForBindingToFilteredObservableCollectionsOnWindowsPhone8.aspx – Rodrigo Vedovato Apr 11 '16 at 13:54

1 Answers1

3

Cant see all of you objects but here is a quick n simple illustration...

    public RelayCommand<int> FilterAgeCommand { get; set; }

    public Base_ViewModel()
    {
        FilterAgeCommand = new RelayCommand<int>(OnFilterAgeCommand);

        this.TestClassList = new ObservableCollection<TestClass>();

        this.TestClassList.Add(new TestClass() { FName = "John", SName = "Doe", Age = 25 });
        this.TestClassList.Add(new TestClass() { FName = "Jane", SName = "Doe", Age = 75 });
        this.TestClassList.Add(new TestClass() { FName = "Mick", SName = "Doe", Age = 35 });
        this.TestClassList.Add(new TestClass() { FName = "Harry", SName = "Doe", Age = 10 });
        this.TestClassList.Add(new TestClass() { FName = "Linda", SName = "Doe", Age = 25 });
        this.TestClassList.Add(new TestClass() { FName = "Fred", SName = "Doe", Age = 14 });

        this.FilteredTestClassList = new ObservableCollection<TestClass>();

        this.Age = new List<int>();
        for(int i = 1; i <100; i++)
        {
            this.Age.Add(i);
        }
    }

    private void OnFilterAgeCommand(int obj)
    {
        this.FilteredTestClassList = Convert<TestClass>((from tc in this.TestClassList where tc.Age < obj select tc).ToList());
    }

    public List<int> Age { get; set; }

    public ObservableCollection<TestClass> TestClassList { get; set; }

    private ObservableCollection<TestClass> _FilteredTestClassList;

    public ObservableCollection<TestClass> FilteredTestClassList 
    {
        get { return _FilteredTestClassList; }
        set { _FilteredTestClassList = value; OnPropertyChanged("FilteredTestClassList"); }
    }

    public ObservableCollection<T> Convert<T>(IEnumerable original)
    {
        return new ObservableCollection<T>(original.Cast<T>());
    }

A simple class for the demo...

public class TestClass : INotifyPropertyChanged
{
private string _FName;

public string FName
{
    get { return _FName; }
    set { _FName = value; NotifyPropertyChanged("FName"); }
}

private string _SName;

public string SName
{
    get { return _SName; }
    set { _SName = value; NotifyPropertyChanged("FName"); }
}

private int _Age;

public int Age
{
    get { return _Age; }
    set { _Age = value; }
}


public event PropertyChangedEventHandler PropertyChanged;

private void NotifyPropertyChanged(String info)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}
}

And some XAML...

            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:ViewModels="clr-namespace:_36550006.ViewModels"
            xmlns:Views="clr-namespace:_36550006.Views" 
            xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
            xmlns:ei="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
            Title="Base_View" Height="300" Width="300">


<Window.DataContext>
    <ViewModels:Base_ViewModel/>
</Window.DataContext>

<Grid>
    <StackPanel>
        <DataGrid ItemsSource="{Binding FilteredTestClassList, NotifyOnSourceUpdated=True}"></DataGrid>
        <ComboBox x:Name="cmb" ItemsSource="{Binding Age}" SelectedValuePath="{Binding Age}" >
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectionChanged">
                    <i:InvokeCommandAction Command="{Binding FilterAgeCommand}" CommandParameter="{Binding ElementName=cmb, Path=SelectedItem}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </ComboBox>
    </StackPanel>
</Grid>

I essentially have two ObservableCollection, the first holds ALL of your items and the second is a filtered collection that you bind to....

Monty
  • 1,534
  • 2
  • 10
  • 12
  • Thanks a lot, had just been going blind and not realizing that I needed 2 seperated collections, 1 filtered and unfiltered. – Sinnich Apr 12 '16 at 06:43