Accessing attached property collection from ViewModel





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







0















I have a custom control LookupPanelView which consists of a TextBox and a ListBox. It has an attached property ItemsSource which the ListBox binds to so the bound data can be set from outside the control.



LookupPanelView



public partial class LookupPanelView : UserControl
{
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(LookupPanelView));

public IEnumerable ItemsSource
{
get => (IEnumerable)GetValue(ItemsSourceProperty);
set => SetValue(ItemsSourceProperty, value);
}

public LookupPanelView()
{
InitializeComponent();
}
}


The control's ItemsSource is bound to a property in my main ViewModel which decides what data to display.



public class MainViewModel : ViewModelBase
{
public ObservableCollection<DomainObject> LookupPanelItems { get; private set; }

public MainViewModel()
{
LookupPanelItems = // Fetch the data to display in the control.
}
}




<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
UseLayoutRounding="True">
<Grid>
<lookupPanelView:LookupPanelView Grid.Column="0" ItemsSource="{Binding LookupPanelItems}"/>
</Grid>




I would like to extend the custom control to have search functionality where you type in the TextBox and it selects a matching item from the ListBox. This logic should be contained in the control since it should be aware of how to search it's own items. I think I need to give the control it's own ViewModel to hold the logic but then how do I access the attached property ItemsSource in the ViewModel to search the items? I would like to avoid using code-behind as much as possible for maintainability and testability.










share|improve this question























  • I would vote against the ViewModel for a UserControl. This functionality is specific to the UserControl and should never have any connection with ViewModel it should only expect data and filter. BTW LookupPanelView reeks of DevExpress.

    – XAMlMAX
    Jan 3 at 15:29











  • @XAMlMAX Thanks for your suggestion. Would you implement it with old-school style events in the code behind then? I'm not sure what you mean "reeks of DevExpress"?

    – Codemunkie
    Jan 3 at 15:45











  • The idea behind the user controls is that they should operate without knowledge about view models. So your control should filter the items it has in it's collection, and that is it's ONLY concern. When I used UC's that's what I did with code behind. Just make sure to implement it for general purpose and not dependant on a specific type of objects in it's collection. And for Dx never mind :-)

    – XAMlMAX
    Jan 3 at 15:58


















0















I have a custom control LookupPanelView which consists of a TextBox and a ListBox. It has an attached property ItemsSource which the ListBox binds to so the bound data can be set from outside the control.



LookupPanelView



public partial class LookupPanelView : UserControl
{
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(LookupPanelView));

public IEnumerable ItemsSource
{
get => (IEnumerable)GetValue(ItemsSourceProperty);
set => SetValue(ItemsSourceProperty, value);
}

public LookupPanelView()
{
InitializeComponent();
}
}


The control's ItemsSource is bound to a property in my main ViewModel which decides what data to display.



public class MainViewModel : ViewModelBase
{
public ObservableCollection<DomainObject> LookupPanelItems { get; private set; }

public MainViewModel()
{
LookupPanelItems = // Fetch the data to display in the control.
}
}




<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
UseLayoutRounding="True">
<Grid>
<lookupPanelView:LookupPanelView Grid.Column="0" ItemsSource="{Binding LookupPanelItems}"/>
</Grid>




I would like to extend the custom control to have search functionality where you type in the TextBox and it selects a matching item from the ListBox. This logic should be contained in the control since it should be aware of how to search it's own items. I think I need to give the control it's own ViewModel to hold the logic but then how do I access the attached property ItemsSource in the ViewModel to search the items? I would like to avoid using code-behind as much as possible for maintainability and testability.










share|improve this question























  • I would vote against the ViewModel for a UserControl. This functionality is specific to the UserControl and should never have any connection with ViewModel it should only expect data and filter. BTW LookupPanelView reeks of DevExpress.

    – XAMlMAX
    Jan 3 at 15:29











  • @XAMlMAX Thanks for your suggestion. Would you implement it with old-school style events in the code behind then? I'm not sure what you mean "reeks of DevExpress"?

    – Codemunkie
    Jan 3 at 15:45











  • The idea behind the user controls is that they should operate without knowledge about view models. So your control should filter the items it has in it's collection, and that is it's ONLY concern. When I used UC's that's what I did with code behind. Just make sure to implement it for general purpose and not dependant on a specific type of objects in it's collection. And for Dx never mind :-)

    – XAMlMAX
    Jan 3 at 15:58














0












0








0








I have a custom control LookupPanelView which consists of a TextBox and a ListBox. It has an attached property ItemsSource which the ListBox binds to so the bound data can be set from outside the control.



LookupPanelView



public partial class LookupPanelView : UserControl
{
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(LookupPanelView));

public IEnumerable ItemsSource
{
get => (IEnumerable)GetValue(ItemsSourceProperty);
set => SetValue(ItemsSourceProperty, value);
}

public LookupPanelView()
{
InitializeComponent();
}
}


The control's ItemsSource is bound to a property in my main ViewModel which decides what data to display.



public class MainViewModel : ViewModelBase
{
public ObservableCollection<DomainObject> LookupPanelItems { get; private set; }

public MainViewModel()
{
LookupPanelItems = // Fetch the data to display in the control.
}
}




<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
UseLayoutRounding="True">
<Grid>
<lookupPanelView:LookupPanelView Grid.Column="0" ItemsSource="{Binding LookupPanelItems}"/>
</Grid>




I would like to extend the custom control to have search functionality where you type in the TextBox and it selects a matching item from the ListBox. This logic should be contained in the control since it should be aware of how to search it's own items. I think I need to give the control it's own ViewModel to hold the logic but then how do I access the attached property ItemsSource in the ViewModel to search the items? I would like to avoid using code-behind as much as possible for maintainability and testability.










share|improve this question














I have a custom control LookupPanelView which consists of a TextBox and a ListBox. It has an attached property ItemsSource which the ListBox binds to so the bound data can be set from outside the control.



LookupPanelView



public partial class LookupPanelView : UserControl
{
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(LookupPanelView));

public IEnumerable ItemsSource
{
get => (IEnumerable)GetValue(ItemsSourceProperty);
set => SetValue(ItemsSourceProperty, value);
}

public LookupPanelView()
{
InitializeComponent();
}
}


The control's ItemsSource is bound to a property in my main ViewModel which decides what data to display.



public class MainViewModel : ViewModelBase
{
public ObservableCollection<DomainObject> LookupPanelItems { get; private set; }

public MainViewModel()
{
LookupPanelItems = // Fetch the data to display in the control.
}
}




<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
UseLayoutRounding="True">
<Grid>
<lookupPanelView:LookupPanelView Grid.Column="0" ItemsSource="{Binding LookupPanelItems}"/>
</Grid>




I would like to extend the custom control to have search functionality where you type in the TextBox and it selects a matching item from the ListBox. This logic should be contained in the control since it should be aware of how to search it's own items. I think I need to give the control it's own ViewModel to hold the logic but then how do I access the attached property ItemsSource in the ViewModel to search the items? I would like to avoid using code-behind as much as possible for maintainability and testability.







c# wpf mvvm binding viewmodel






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Jan 3 at 12:19









CodemunkieCodemunkie

518




518













  • I would vote against the ViewModel for a UserControl. This functionality is specific to the UserControl and should never have any connection with ViewModel it should only expect data and filter. BTW LookupPanelView reeks of DevExpress.

    – XAMlMAX
    Jan 3 at 15:29











  • @XAMlMAX Thanks for your suggestion. Would you implement it with old-school style events in the code behind then? I'm not sure what you mean "reeks of DevExpress"?

    – Codemunkie
    Jan 3 at 15:45











  • The idea behind the user controls is that they should operate without knowledge about view models. So your control should filter the items it has in it's collection, and that is it's ONLY concern. When I used UC's that's what I did with code behind. Just make sure to implement it for general purpose and not dependant on a specific type of objects in it's collection. And for Dx never mind :-)

    – XAMlMAX
    Jan 3 at 15:58



















  • I would vote against the ViewModel for a UserControl. This functionality is specific to the UserControl and should never have any connection with ViewModel it should only expect data and filter. BTW LookupPanelView reeks of DevExpress.

    – XAMlMAX
    Jan 3 at 15:29











  • @XAMlMAX Thanks for your suggestion. Would you implement it with old-school style events in the code behind then? I'm not sure what you mean "reeks of DevExpress"?

    – Codemunkie
    Jan 3 at 15:45











  • The idea behind the user controls is that they should operate without knowledge about view models. So your control should filter the items it has in it's collection, and that is it's ONLY concern. When I used UC's that's what I did with code behind. Just make sure to implement it for general purpose and not dependant on a specific type of objects in it's collection. And for Dx never mind :-)

    – XAMlMAX
    Jan 3 at 15:58

















I would vote against the ViewModel for a UserControl. This functionality is specific to the UserControl and should never have any connection with ViewModel it should only expect data and filter. BTW LookupPanelView reeks of DevExpress.

– XAMlMAX
Jan 3 at 15:29





I would vote against the ViewModel for a UserControl. This functionality is specific to the UserControl and should never have any connection with ViewModel it should only expect data and filter. BTW LookupPanelView reeks of DevExpress.

– XAMlMAX
Jan 3 at 15:29













@XAMlMAX Thanks for your suggestion. Would you implement it with old-school style events in the code behind then? I'm not sure what you mean "reeks of DevExpress"?

– Codemunkie
Jan 3 at 15:45





@XAMlMAX Thanks for your suggestion. Would you implement it with old-school style events in the code behind then? I'm not sure what you mean "reeks of DevExpress"?

– Codemunkie
Jan 3 at 15:45













The idea behind the user controls is that they should operate without knowledge about view models. So your control should filter the items it has in it's collection, and that is it's ONLY concern. When I used UC's that's what I did with code behind. Just make sure to implement it for general purpose and not dependant on a specific type of objects in it's collection. And for Dx never mind :-)

– XAMlMAX
Jan 3 at 15:58





The idea behind the user controls is that they should operate without knowledge about view models. So your control should filter the items it has in it's collection, and that is it's ONLY concern. When I used UC's that's what I did with code behind. Just make sure to implement it for general purpose and not dependant on a specific type of objects in it's collection. And for Dx never mind :-)

– XAMlMAX
Jan 3 at 15:58












3 Answers
3






active

oldest

votes


















0














CollectionViewSource with Filter will do the trick.



Here is the basic sample to use Filter on search using CollectionViewSource






share|improve this answer


























  • Is it possible to use this technique to highlight the matching item without affecting the rest of the list? I.e. not filter the list but just select the matching item

    – Codemunkie
    Jan 3 at 13:02











  • The view doesn't return entries which are filtered. You might as well inject a predicate to decide which are to be highlighted.

    – Andy
    Jan 3 at 13:08



















0















This logic should be contained in the control since it should be aware of how to search it's own items.




Why do you need a view model then? If the "logic should be contained in the control", then implement it there.




I think I need to give the control it's own ViewModel to hold the logic but then how do I access the attached property ItemsSource in the ViewModel to search the items?




This is in contradiction to your first sentence, but if the control really needs its own view model for some reason and the view model needs access to the control, you could simply inject with a reference to the control when you create the view model, e.g.:



public LookupPanelView()
{
InitializeComponent();
this.DataContext = new ViewModel(this);
}


But what you probably want is to create a custom control with a default template. This is just a class that inherit from Control and has no code-behind or XAML file. Please refer to this tutorial for an example. A UserControl is more like a composite view than a custom control with its own custom logic.






share|improve this answer
























  • Just a note, if you set up the DataContext of the UC like this then ItemsSource binding will look for that property in the UC and not the DataContext where it is being used. You need to preserve the DataContext inheritance so the Bindings can be resolved correctly.

    – XAMlMAX
    Jan 3 at 18:35



















0














After a bit of thinking I came up with this sort of starting point for you.

First you create your control a bit like this:



<UserControl x:Class="SO_App.UC.SearchableListView"
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:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SO_App.UC"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid x:Name="root"><!-- This allows us to keep the Data Context inheritance -->
<Grid.Resources>
<CollectionViewSource Source="{Binding ItemsSource}" x:Key="Items"/> <!-- This is for us to use Filtering and so on -->
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox x:Name="txtSearch" Text="{Binding SearchTerm}"/>
<!-- Placeholder -->
<TextBlock IsHitTestVisible="False" Text="{Binding SearchTextPlaceHolder,TargetNullValue=Search, FallbackValue=Search}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Foreground="DarkGray">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=txtSearch}" Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<ListView x:Name="lstItems" Grid.Row="1" ItemsSource="{Binding Source={StaticResource Items}}"/>
</Grid>




Root element keeps the Bidning to the user control in tact, while we can use the normal binding from the parent element in our main window.
Then in your MainWindow.xaml you would use it like this:



<Window x:Class="SO_App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:VM;assembly=VM"
xmlns:model="clr-namespace:Model;assembly=Model"
xmlns:converter="clr-namespace:SO_App.Converters"
xmlns:uc="clr-namespace:SO_App.UC"
xmlns:local="clr-namespace:SO_App"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<vm:MainViewModel/>
</Window.DataContext>
<Grid>
<uc:SearchableListView SearchTextPlaceHolder="Search" ItemsSource="{Binding Users}">
<uc:SearchableListView.Resources>
<DataTemplate DataType="{x:Type model:User}">
<Grid>
<StackPanel>
<TextBlock Text="{Binding ID}"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</Grid>
</DataTemplate>
</uc:SearchableListView.Resources>
</uc:SearchableListView>
</Grid>




For the sake of this post here is the ViewModel:



public class MainViewModel : BaseViewModel
{
public MainViewModel()
{
Users = new List<User>();
for (int i = 0; i < 6; i++)
{
Users.Add(new User
{
ID = i,
Name = $"John the {i + 1}",
State = i % 2 == 0 ? "CA" : "IL",
Cases = new List<Case>() { new Case { CaseID = (i + 1) * 10, Vendor = ((i + 1) * 10) - 2 }, new Case { CaseID = (i + 1) * 10, Vendor = ((i + 1) * 10) - 2 } }
});
}
}
}


And here is the user object:



namespace Model
{
public class User//Ideally you would have INPC implemented here
{
public int ID { get; set; }
public string Name { get; set; }
public string State { get; set; }
public List<Case> Cases { get; set; }
}
}


Hope this gives you enough information to start your implementation in the right direction and with as much MvvM as possible.






share|improve this answer
























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54022185%2faccessing-attached-property-collection-from-viewmodel%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    CollectionViewSource with Filter will do the trick.



    Here is the basic sample to use Filter on search using CollectionViewSource






    share|improve this answer


























    • Is it possible to use this technique to highlight the matching item without affecting the rest of the list? I.e. not filter the list but just select the matching item

      – Codemunkie
      Jan 3 at 13:02











    • The view doesn't return entries which are filtered. You might as well inject a predicate to decide which are to be highlighted.

      – Andy
      Jan 3 at 13:08
















    0














    CollectionViewSource with Filter will do the trick.



    Here is the basic sample to use Filter on search using CollectionViewSource






    share|improve this answer


























    • Is it possible to use this technique to highlight the matching item without affecting the rest of the list? I.e. not filter the list but just select the matching item

      – Codemunkie
      Jan 3 at 13:02











    • The view doesn't return entries which are filtered. You might as well inject a predicate to decide which are to be highlighted.

      – Andy
      Jan 3 at 13:08














    0












    0








    0







    CollectionViewSource with Filter will do the trick.



    Here is the basic sample to use Filter on search using CollectionViewSource






    share|improve this answer















    CollectionViewSource with Filter will do the trick.



    Here is the basic sample to use Filter on search using CollectionViewSource







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Jan 3 at 12:58

























    answered Jan 3 at 12:51









    GopichandarGopichandar

    1,75721338




    1,75721338













    • Is it possible to use this technique to highlight the matching item without affecting the rest of the list? I.e. not filter the list but just select the matching item

      – Codemunkie
      Jan 3 at 13:02











    • The view doesn't return entries which are filtered. You might as well inject a predicate to decide which are to be highlighted.

      – Andy
      Jan 3 at 13:08



















    • Is it possible to use this technique to highlight the matching item without affecting the rest of the list? I.e. not filter the list but just select the matching item

      – Codemunkie
      Jan 3 at 13:02











    • The view doesn't return entries which are filtered. You might as well inject a predicate to decide which are to be highlighted.

      – Andy
      Jan 3 at 13:08

















    Is it possible to use this technique to highlight the matching item without affecting the rest of the list? I.e. not filter the list but just select the matching item

    – Codemunkie
    Jan 3 at 13:02





    Is it possible to use this technique to highlight the matching item without affecting the rest of the list? I.e. not filter the list but just select the matching item

    – Codemunkie
    Jan 3 at 13:02













    The view doesn't return entries which are filtered. You might as well inject a predicate to decide which are to be highlighted.

    – Andy
    Jan 3 at 13:08





    The view doesn't return entries which are filtered. You might as well inject a predicate to decide which are to be highlighted.

    – Andy
    Jan 3 at 13:08













    0















    This logic should be contained in the control since it should be aware of how to search it's own items.




    Why do you need a view model then? If the "logic should be contained in the control", then implement it there.




    I think I need to give the control it's own ViewModel to hold the logic but then how do I access the attached property ItemsSource in the ViewModel to search the items?




    This is in contradiction to your first sentence, but if the control really needs its own view model for some reason and the view model needs access to the control, you could simply inject with a reference to the control when you create the view model, e.g.:



    public LookupPanelView()
    {
    InitializeComponent();
    this.DataContext = new ViewModel(this);
    }


    But what you probably want is to create a custom control with a default template. This is just a class that inherit from Control and has no code-behind or XAML file. Please refer to this tutorial for an example. A UserControl is more like a composite view than a custom control with its own custom logic.






    share|improve this answer
























    • Just a note, if you set up the DataContext of the UC like this then ItemsSource binding will look for that property in the UC and not the DataContext where it is being used. You need to preserve the DataContext inheritance so the Bindings can be resolved correctly.

      – XAMlMAX
      Jan 3 at 18:35
















    0















    This logic should be contained in the control since it should be aware of how to search it's own items.




    Why do you need a view model then? If the "logic should be contained in the control", then implement it there.




    I think I need to give the control it's own ViewModel to hold the logic but then how do I access the attached property ItemsSource in the ViewModel to search the items?




    This is in contradiction to your first sentence, but if the control really needs its own view model for some reason and the view model needs access to the control, you could simply inject with a reference to the control when you create the view model, e.g.:



    public LookupPanelView()
    {
    InitializeComponent();
    this.DataContext = new ViewModel(this);
    }


    But what you probably want is to create a custom control with a default template. This is just a class that inherit from Control and has no code-behind or XAML file. Please refer to this tutorial for an example. A UserControl is more like a composite view than a custom control with its own custom logic.






    share|improve this answer
























    • Just a note, if you set up the DataContext of the UC like this then ItemsSource binding will look for that property in the UC and not the DataContext where it is being used. You need to preserve the DataContext inheritance so the Bindings can be resolved correctly.

      – XAMlMAX
      Jan 3 at 18:35














    0












    0








    0








    This logic should be contained in the control since it should be aware of how to search it's own items.




    Why do you need a view model then? If the "logic should be contained in the control", then implement it there.




    I think I need to give the control it's own ViewModel to hold the logic but then how do I access the attached property ItemsSource in the ViewModel to search the items?




    This is in contradiction to your first sentence, but if the control really needs its own view model for some reason and the view model needs access to the control, you could simply inject with a reference to the control when you create the view model, e.g.:



    public LookupPanelView()
    {
    InitializeComponent();
    this.DataContext = new ViewModel(this);
    }


    But what you probably want is to create a custom control with a default template. This is just a class that inherit from Control and has no code-behind or XAML file. Please refer to this tutorial for an example. A UserControl is more like a composite view than a custom control with its own custom logic.






    share|improve this answer














    This logic should be contained in the control since it should be aware of how to search it's own items.




    Why do you need a view model then? If the "logic should be contained in the control", then implement it there.




    I think I need to give the control it's own ViewModel to hold the logic but then how do I access the attached property ItemsSource in the ViewModel to search the items?




    This is in contradiction to your first sentence, but if the control really needs its own view model for some reason and the view model needs access to the control, you could simply inject with a reference to the control when you create the view model, e.g.:



    public LookupPanelView()
    {
    InitializeComponent();
    this.DataContext = new ViewModel(this);
    }


    But what you probably want is to create a custom control with a default template. This is just a class that inherit from Control and has no code-behind or XAML file. Please refer to this tutorial for an example. A UserControl is more like a composite view than a custom control with its own custom logic.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Jan 3 at 16:10









    mm8mm8

    89.2k81934




    89.2k81934













    • Just a note, if you set up the DataContext of the UC like this then ItemsSource binding will look for that property in the UC and not the DataContext where it is being used. You need to preserve the DataContext inheritance so the Bindings can be resolved correctly.

      – XAMlMAX
      Jan 3 at 18:35



















    • Just a note, if you set up the DataContext of the UC like this then ItemsSource binding will look for that property in the UC and not the DataContext where it is being used. You need to preserve the DataContext inheritance so the Bindings can be resolved correctly.

      – XAMlMAX
      Jan 3 at 18:35

















    Just a note, if you set up the DataContext of the UC like this then ItemsSource binding will look for that property in the UC and not the DataContext where it is being used. You need to preserve the DataContext inheritance so the Bindings can be resolved correctly.

    – XAMlMAX
    Jan 3 at 18:35





    Just a note, if you set up the DataContext of the UC like this then ItemsSource binding will look for that property in the UC and not the DataContext where it is being used. You need to preserve the DataContext inheritance so the Bindings can be resolved correctly.

    – XAMlMAX
    Jan 3 at 18:35











    0














    After a bit of thinking I came up with this sort of starting point for you.

    First you create your control a bit like this:



    <UserControl x:Class="SO_App.UC.SearchableListView"
    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:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:SO_App.UC"
    mc:Ignorable="d"
    d:DesignHeight="450" d:DesignWidth="800">
    <Grid x:Name="root"><!-- This allows us to keep the Data Context inheritance -->
    <Grid.Resources>
    <CollectionViewSource Source="{Binding ItemsSource}" x:Key="Items"/> <!-- This is for us to use Filtering and so on -->
    </Grid.Resources>
    <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition/>
    </Grid.RowDefinitions>
    <TextBox x:Name="txtSearch" Text="{Binding SearchTerm}"/>
    <!-- Placeholder -->
    <TextBlock IsHitTestVisible="False" Text="{Binding SearchTextPlaceHolder,TargetNullValue=Search, FallbackValue=Search}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Foreground="DarkGray">
    <TextBlock.Style>
    <Style TargetType="{x:Type TextBlock}">
    <Setter Property="Visibility" Value="Collapsed"/>
    <Style.Triggers>
    <DataTrigger Binding="{Binding Text, ElementName=txtSearch}" Value="">
    <Setter Property="Visibility" Value="Visible"/>
    </DataTrigger>
    </Style.Triggers>
    </Style>
    </TextBlock.Style>
    </TextBlock>
    <ListView x:Name="lstItems" Grid.Row="1" ItemsSource="{Binding Source={StaticResource Items}}"/>
    </Grid>




    Root element keeps the Bidning to the user control in tact, while we can use the normal binding from the parent element in our main window.
    Then in your MainWindow.xaml you would use it like this:



    <Window x:Class="SO_App.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:vm="clr-namespace:VM;assembly=VM"
    xmlns:model="clr-namespace:Model;assembly=Model"
    xmlns:converter="clr-namespace:SO_App.Converters"
    xmlns:uc="clr-namespace:SO_App.UC"
    xmlns:local="clr-namespace:SO_App"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
    <vm:MainViewModel/>
    </Window.DataContext>
    <Grid>
    <uc:SearchableListView SearchTextPlaceHolder="Search" ItemsSource="{Binding Users}">
    <uc:SearchableListView.Resources>
    <DataTemplate DataType="{x:Type model:User}">
    <Grid>
    <StackPanel>
    <TextBlock Text="{Binding ID}"/>
    <TextBlock Text="{Binding Name}"/>
    </StackPanel>
    </Grid>
    </DataTemplate>
    </uc:SearchableListView.Resources>
    </uc:SearchableListView>
    </Grid>




    For the sake of this post here is the ViewModel:



    public class MainViewModel : BaseViewModel
    {
    public MainViewModel()
    {
    Users = new List<User>();
    for (int i = 0; i < 6; i++)
    {
    Users.Add(new User
    {
    ID = i,
    Name = $"John the {i + 1}",
    State = i % 2 == 0 ? "CA" : "IL",
    Cases = new List<Case>() { new Case { CaseID = (i + 1) * 10, Vendor = ((i + 1) * 10) - 2 }, new Case { CaseID = (i + 1) * 10, Vendor = ((i + 1) * 10) - 2 } }
    });
    }
    }
    }


    And here is the user object:



    namespace Model
    {
    public class User//Ideally you would have INPC implemented here
    {
    public int ID { get; set; }
    public string Name { get; set; }
    public string State { get; set; }
    public List<Case> Cases { get; set; }
    }
    }


    Hope this gives you enough information to start your implementation in the right direction and with as much MvvM as possible.






    share|improve this answer




























      0














      After a bit of thinking I came up with this sort of starting point for you.

      First you create your control a bit like this:



      <UserControl x:Class="SO_App.UC.SearchableListView"
      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:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:local="clr-namespace:SO_App.UC"
      mc:Ignorable="d"
      d:DesignHeight="450" d:DesignWidth="800">
      <Grid x:Name="root"><!-- This allows us to keep the Data Context inheritance -->
      <Grid.Resources>
      <CollectionViewSource Source="{Binding ItemsSource}" x:Key="Items"/> <!-- This is for us to use Filtering and so on -->
      </Grid.Resources>
      <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition/>
      </Grid.RowDefinitions>
      <TextBox x:Name="txtSearch" Text="{Binding SearchTerm}"/>
      <!-- Placeholder -->
      <TextBlock IsHitTestVisible="False" Text="{Binding SearchTextPlaceHolder,TargetNullValue=Search, FallbackValue=Search}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Foreground="DarkGray">
      <TextBlock.Style>
      <Style TargetType="{x:Type TextBlock}">
      <Setter Property="Visibility" Value="Collapsed"/>
      <Style.Triggers>
      <DataTrigger Binding="{Binding Text, ElementName=txtSearch}" Value="">
      <Setter Property="Visibility" Value="Visible"/>
      </DataTrigger>
      </Style.Triggers>
      </Style>
      </TextBlock.Style>
      </TextBlock>
      <ListView x:Name="lstItems" Grid.Row="1" ItemsSource="{Binding Source={StaticResource Items}}"/>
      </Grid>




      Root element keeps the Bidning to the user control in tact, while we can use the normal binding from the parent element in our main window.
      Then in your MainWindow.xaml you would use it like this:



      <Window x:Class="SO_App.MainWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:vm="clr-namespace:VM;assembly=VM"
      xmlns:model="clr-namespace:Model;assembly=Model"
      xmlns:converter="clr-namespace:SO_App.Converters"
      xmlns:uc="clr-namespace:SO_App.UC"
      xmlns:local="clr-namespace:SO_App"
      xmlns:sys="clr-namespace:System;assembly=mscorlib"
      mc:Ignorable="d"
      Title="MainWindow" Height="350" Width="525">
      <Window.DataContext>
      <vm:MainViewModel/>
      </Window.DataContext>
      <Grid>
      <uc:SearchableListView SearchTextPlaceHolder="Search" ItemsSource="{Binding Users}">
      <uc:SearchableListView.Resources>
      <DataTemplate DataType="{x:Type model:User}">
      <Grid>
      <StackPanel>
      <TextBlock Text="{Binding ID}"/>
      <TextBlock Text="{Binding Name}"/>
      </StackPanel>
      </Grid>
      </DataTemplate>
      </uc:SearchableListView.Resources>
      </uc:SearchableListView>
      </Grid>




      For the sake of this post here is the ViewModel:



      public class MainViewModel : BaseViewModel
      {
      public MainViewModel()
      {
      Users = new List<User>();
      for (int i = 0; i < 6; i++)
      {
      Users.Add(new User
      {
      ID = i,
      Name = $"John the {i + 1}",
      State = i % 2 == 0 ? "CA" : "IL",
      Cases = new List<Case>() { new Case { CaseID = (i + 1) * 10, Vendor = ((i + 1) * 10) - 2 }, new Case { CaseID = (i + 1) * 10, Vendor = ((i + 1) * 10) - 2 } }
      });
      }
      }
      }


      And here is the user object:



      namespace Model
      {
      public class User//Ideally you would have INPC implemented here
      {
      public int ID { get; set; }
      public string Name { get; set; }
      public string State { get; set; }
      public List<Case> Cases { get; set; }
      }
      }


      Hope this gives you enough information to start your implementation in the right direction and with as much MvvM as possible.






      share|improve this answer


























        0












        0








        0







        After a bit of thinking I came up with this sort of starting point for you.

        First you create your control a bit like this:



        <UserControl x:Class="SO_App.UC.SearchableListView"
        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:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:SO_App.UC"
        mc:Ignorable="d"
        d:DesignHeight="450" d:DesignWidth="800">
        <Grid x:Name="root"><!-- This allows us to keep the Data Context inheritance -->
        <Grid.Resources>
        <CollectionViewSource Source="{Binding ItemsSource}" x:Key="Items"/> <!-- This is for us to use Filtering and so on -->
        </Grid.Resources>
        <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBox x:Name="txtSearch" Text="{Binding SearchTerm}"/>
        <!-- Placeholder -->
        <TextBlock IsHitTestVisible="False" Text="{Binding SearchTextPlaceHolder,TargetNullValue=Search, FallbackValue=Search}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Foreground="DarkGray">
        <TextBlock.Style>
        <Style TargetType="{x:Type TextBlock}">
        <Setter Property="Visibility" Value="Collapsed"/>
        <Style.Triggers>
        <DataTrigger Binding="{Binding Text, ElementName=txtSearch}" Value="">
        <Setter Property="Visibility" Value="Visible"/>
        </DataTrigger>
        </Style.Triggers>
        </Style>
        </TextBlock.Style>
        </TextBlock>
        <ListView x:Name="lstItems" Grid.Row="1" ItemsSource="{Binding Source={StaticResource Items}}"/>
        </Grid>




        Root element keeps the Bidning to the user control in tact, while we can use the normal binding from the parent element in our main window.
        Then in your MainWindow.xaml you would use it like this:



        <Window x:Class="SO_App.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="clr-namespace:VM;assembly=VM"
        xmlns:model="clr-namespace:Model;assembly=Model"
        xmlns:converter="clr-namespace:SO_App.Converters"
        xmlns:uc="clr-namespace:SO_App.UC"
        xmlns:local="clr-namespace:SO_App"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
        <Window.DataContext>
        <vm:MainViewModel/>
        </Window.DataContext>
        <Grid>
        <uc:SearchableListView SearchTextPlaceHolder="Search" ItemsSource="{Binding Users}">
        <uc:SearchableListView.Resources>
        <DataTemplate DataType="{x:Type model:User}">
        <Grid>
        <StackPanel>
        <TextBlock Text="{Binding ID}"/>
        <TextBlock Text="{Binding Name}"/>
        </StackPanel>
        </Grid>
        </DataTemplate>
        </uc:SearchableListView.Resources>
        </uc:SearchableListView>
        </Grid>




        For the sake of this post here is the ViewModel:



        public class MainViewModel : BaseViewModel
        {
        public MainViewModel()
        {
        Users = new List<User>();
        for (int i = 0; i < 6; i++)
        {
        Users.Add(new User
        {
        ID = i,
        Name = $"John the {i + 1}",
        State = i % 2 == 0 ? "CA" : "IL",
        Cases = new List<Case>() { new Case { CaseID = (i + 1) * 10, Vendor = ((i + 1) * 10) - 2 }, new Case { CaseID = (i + 1) * 10, Vendor = ((i + 1) * 10) - 2 } }
        });
        }
        }
        }


        And here is the user object:



        namespace Model
        {
        public class User//Ideally you would have INPC implemented here
        {
        public int ID { get; set; }
        public string Name { get; set; }
        public string State { get; set; }
        public List<Case> Cases { get; set; }
        }
        }


        Hope this gives you enough information to start your implementation in the right direction and with as much MvvM as possible.






        share|improve this answer













        After a bit of thinking I came up with this sort of starting point for you.

        First you create your control a bit like this:



        <UserControl x:Class="SO_App.UC.SearchableListView"
        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:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:local="clr-namespace:SO_App.UC"
        mc:Ignorable="d"
        d:DesignHeight="450" d:DesignWidth="800">
        <Grid x:Name="root"><!-- This allows us to keep the Data Context inheritance -->
        <Grid.Resources>
        <CollectionViewSource Source="{Binding ItemsSource}" x:Key="Items"/> <!-- This is for us to use Filtering and so on -->
        </Grid.Resources>
        <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBox x:Name="txtSearch" Text="{Binding SearchTerm}"/>
        <!-- Placeholder -->
        <TextBlock IsHitTestVisible="False" Text="{Binding SearchTextPlaceHolder,TargetNullValue=Search, FallbackValue=Search}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0,0,0" Foreground="DarkGray">
        <TextBlock.Style>
        <Style TargetType="{x:Type TextBlock}">
        <Setter Property="Visibility" Value="Collapsed"/>
        <Style.Triggers>
        <DataTrigger Binding="{Binding Text, ElementName=txtSearch}" Value="">
        <Setter Property="Visibility" Value="Visible"/>
        </DataTrigger>
        </Style.Triggers>
        </Style>
        </TextBlock.Style>
        </TextBlock>
        <ListView x:Name="lstItems" Grid.Row="1" ItemsSource="{Binding Source={StaticResource Items}}"/>
        </Grid>




        Root element keeps the Bidning to the user control in tact, while we can use the normal binding from the parent element in our main window.
        Then in your MainWindow.xaml you would use it like this:



        <Window x:Class="SO_App.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="clr-namespace:VM;assembly=VM"
        xmlns:model="clr-namespace:Model;assembly=Model"
        xmlns:converter="clr-namespace:SO_App.Converters"
        xmlns:uc="clr-namespace:SO_App.UC"
        xmlns:local="clr-namespace:SO_App"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
        <Window.DataContext>
        <vm:MainViewModel/>
        </Window.DataContext>
        <Grid>
        <uc:SearchableListView SearchTextPlaceHolder="Search" ItemsSource="{Binding Users}">
        <uc:SearchableListView.Resources>
        <DataTemplate DataType="{x:Type model:User}">
        <Grid>
        <StackPanel>
        <TextBlock Text="{Binding ID}"/>
        <TextBlock Text="{Binding Name}"/>
        </StackPanel>
        </Grid>
        </DataTemplate>
        </uc:SearchableListView.Resources>
        </uc:SearchableListView>
        </Grid>




        For the sake of this post here is the ViewModel:



        public class MainViewModel : BaseViewModel
        {
        public MainViewModel()
        {
        Users = new List<User>();
        for (int i = 0; i < 6; i++)
        {
        Users.Add(new User
        {
        ID = i,
        Name = $"John the {i + 1}",
        State = i % 2 == 0 ? "CA" : "IL",
        Cases = new List<Case>() { new Case { CaseID = (i + 1) * 10, Vendor = ((i + 1) * 10) - 2 }, new Case { CaseID = (i + 1) * 10, Vendor = ((i + 1) * 10) - 2 } }
        });
        }
        }
        }


        And here is the user object:



        namespace Model
        {
        public class User//Ideally you would have INPC implemented here
        {
        public int ID { get; set; }
        public string Name { get; set; }
        public string State { get; set; }
        public List<Case> Cases { get; set; }
        }
        }


        Hope this gives you enough information to start your implementation in the right direction and with as much MvvM as possible.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Jan 3 at 20:30









        XAMlMAXXAMlMAX

        1,8731920




        1,8731920






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54022185%2faccessing-attached-property-collection-from-viewmodel%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            MongoDB - Not Authorized To Execute Command

            in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith

            How to fix TextFormField cause rebuild widget in Flutter