Подумав немного, я придумал для вас такую отправную точку.
Сначала вы создаете свой элемент управления примерно так:
<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>
Корневой элемент сохраняет Bidningпользовательский элемент управления в такте, в то время как мы можем использовать обычную привязку от родительского элемента в нашем главном окне.Тогда в вашем MainWindow.xaml вы бы использовали его так:
<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>
Ради этого поста здесь есть 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 } }
});
}
}
}
А вотпользовательский объект:
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; }
}
}
Надеюсь, что это даст вам достаточно информации, чтобы начать реализацию в правильном направлении и с как можно большим количеством MvvM.