WPF ListView show Image - wpf

I have a simple class that contains a string and an WPF Image control:
public class User
{
public string Name { get; set; }
public System.Windows.Controls.Image Image { get; set; }
}
Now I'm binding a list of instances of this class to a ListView.
What I would like to do now is make ListView display the Image property.
I've tried settings DisplayMemberPath to Image, but this shows the ToString value of Image instead (System.Windows.Controls.Image).
How can I make it actually show the control?
Here's the XAML code:
<ListView Name="listView1" DisplayMemberPath="Image" />
Thanks!

You could create a DataTemplate that uses a ContentPresenter to display the image:
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding Image}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Related

How to binding TextBlock text in TabControl ItemTemplate?

In sidebar menu(RTL) when i clicked on which one, a TabItem added to tbMain. My problem is that how i can show sidebar clicked text in TabItem header in TextBlock using Binding?
here is Image , XAML and CodeBehind.
XAML:
<TabControl x:Name="tbMain" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="6" Grid.RowSpan="5" Margin="0">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}" VerticalAlignment="Center" Foreground="#000000"/>
</DataTemplate>
</TabControl.ItemTemplate>
Code Behind :
public WinFinance() {
InitializeComponent();
var definitionsMenu = new List<MenuSubItems>();
definitionsMenu.Add(new MenuSubItems("area", new ucrArea()));
definitionsMenu.Add(new MenuSubItems("client", new ucrClient()));
definitionsMenu.Add(new MenuSubItems("cash" , new ucrCash()));
tbMain.Items.Add(new ucrMainControl());
}
First of all, I will assume that you somehow made that List<MenuSubItems> as ItemsSource of tbMain in the part of code that you didn't uploaded.
In this case, If you want to make some string property("area", "client", "cash"...) as a Header of TabItems, You can use Style like:
<TabControl x:Name="tbMain" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="6" Grid.RowSpan="5" Margin="0">
<TabControl.ItemContainerStyle>
<Style TargetType="TabItem">
<Setter Property="Header" Value="{Binding MenuSubHeader}"/>
</Style>
</TabControl.ItemContainerStyle>
.......
Then it will works.
Edit: This was my code-behind and MenuSubItems class I wrote. I don't have any knowledge about your project so I just wrote just to show how it works.
public MainWindow()
{
InitializeComponent();
var definitionsMenu = new List<MenuSubItems>();
definitionsMenu.Add(new MenuSubItems("area", new object()));
definitionsMenu.Add(new MenuSubItems("client", new object()));
definitionsMenu.Add(new MenuSubItems("cash", new object()));
tbMain.ItemsSource = definitionsMenu;
}
public class MenuSubItems
{
public string MenuSubHeader { get; set; }
public object Content { get; set; }
public MenuSubItems(string key, object value)
{
MenuSubHeader = key;
Content = value;
}
}
For it to be achieved the way you're XAML is wrote, you must have Items that has a property named Text (also, if you want it to update itself dynamically, implement INotifyProperty).
The best way to do that is by creating a ViewModel with the data you need and bind you're sidebar values with the same property that you bind the tabs.

Images disappear from the ListView in WPF after an action

Images load correctly to the listview, but whenever I click on the listview and change the SelectedItem, the images dissapear. I can see the elements and do everything with them, but they are a simple row and the image itself is not in the row.
This is the XAML for the ListView
<ListView Name="testLB" ItemsSource="{Binding Images}" SelectedItem="{Binding SelectedImage}" HorizontalAlignment="Left" Height="393" Margin="627,28,0,0" VerticalAlignment="Top" Width="244" SelectionChanged="testLB_SelectionChanged"/>
And this is part of my ViewModel.
public ObservableCollection<Image> Images { get; private set; }
public Image SelectedImage { get => selectedImage;
set {
this.selectedImage = value;
this.OnPropertyChanged("SelectedImage");
} }
private Image selectedImage;
Image is a subclass of UIElement, and should hence not be used as item type in a view model.
Use ImageSource instead (and add e.g. BitmapImages or BitmapFrames to your collection):
public ObservableCollection<ImageSource> Images { get; private set; }
public ImageSource SelectedImage { ... }
Then make your ListView's ItemTemplate contain an Image element:
<ListView ItemsSource="{Binding Images}" SelectedItem="{Binding SelectedImage}" ...>
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

How to pass listbox selecteditem as command parameter in a button?

Here is my situation:
<ListBox ItemsSource="{Binding Path=AvailableUsers}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Id}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Command="{Binding Path=Load}" CommandParameter={???? What goes here ????}/>
What I want is to pass the Id that is currently selected in the ListBox. I have a viewmodel behind the scenes that essentially looks like this:
public class ViewModel : DependencyObject
{
ICommand Load { get; set; }
// dependency property but I didn't bother to write it out like one
List<User> AvailableUsers { get; set}
}
How can I send the currently selected item using the xaml?
Try this:
Name your listbox
Update the CommandParameter to:
CommandParameter="{Binding ElementName=listBox1,Path=SelectedItem}"

How do I bind to something outside a datacontext

I have a listbox in WPF that is in the Layout Root.
I also have a Frame that is in the Layout Root as well.
The listbox is composed of items that have a string(Name) and a framework element(UI).
How do I bind the frame's content to be the UI property of the listbox's selected item property?
If you need a codebehind, how would you do this in MVVM
I used a ContentControl instead of Frame since I had problem binding to Content property, I never got it to refresh after binding changed. I didn't do proper MVVM, Data should not be hosted inside the view.
XAML:
<Window.Resources>
<CollectionViewSource x:Key="CVS" Source="{Binding}" />
</Window.Resources>
<StackPanel DataContext="{Binding Source={StaticResource CVS}}">
<ListBox
ItemsSource="{Binding}"
IsSynchronizedWithCurrentItem="True"
DisplayMemberPath="Name">
</ListBox>
<ContentControl Content="{Binding Path=UI}" />
</StackPanel>
Code behind:
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace BindDemo
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
Data = new List<DataItem>();
Data.Add(new DataItem("TextBox", new TextBox(){ Text="hello" }));
Data.Add(new DataItem("ComboBox", new ComboBox()));
Data.Add(new DataItem("Slider", new Slider()));
DataContext = Data;
}
public List<DataItem> Data
{
get; private set;
}
}
public class DataItem
{
public DataItem(string name, FrameworkElement ui)
{
Name = name;
UI = ui;
}
public string Name { get; private set; }
public FrameworkElement UI { get; private set; }
}
}
It sounds as you want to display list of objects and details for selected object. If I am right, solution in MVVM may be following:
<ListView ItemsSource="{Binding ObjectsList}" IsSynchronizedWithCurrentItem="True" />
<ContentControl Content="{Binding ObjectsList}">
<ContentControl.ContentTemplate>
<DataTemplate>
<!-- details template -->
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>

How to set Itemsource to a Comobox Inside a DataTemplate Dynamically?

I have one Listbox and applied one DataTemplate like this
<ListBox>
<ListBox.ItemTemplate>
<Grid>
<TextBlock Text="{Binding Path=Name}" Grid.Row=0/>
<ComoboBox Name="test"
DisplayMemberPath="Country"
SelectedValuePath="Country_ID">
</Grid>
How will I load ItemSource to this ComboBox dynamically based on each item selected in the ListBox? Iam new to WPF... pls help with your valuable suggestions.
<ListBox>
<ListBox.ItemTemplate>
<Grid>
<TextBlock Text="{Binding Path=Name}" Grid.Row=0/>
<ComoboBox Name="test"
DataContent="{Binding RelativeSource={RelativeSource AncestorType=ListBox}}"
ItemsSource="{Binding}"
DisplayMemberPath="Country"
SelectedValuePath="Country_ID">
</Grid>
Now your combocbox is always have the same itemssource as the parent listbox.
One way to do this is to bind the ItemsSource of your ComboBox to the SelectedValue property of the ListBox. For this to work the ListBox needs to be bound to a collection of items that contains a list of items that the ComboBox will bind to.
<ListBox
x:Name="CategoryList"
ItemsSource="{Binding Path=MasterList,
RelativeSource={RelativeSource AncestorType=Window}}"
DisplayMemberPath="MasterProperty"
SelectedValuePath="Details"
/>
<ComboBox
ItemsSource="{Binding Path=SelectedValue, ElementName=CategoryList}"
DisplayMemberPath="DetailProperty"
Grid.Row="1"
/>
In this example I have created a public property in the code behind of the window that exposes a list of objects containing the Details collection.
public List<Master> MasterList { get; set; }
public class Master
{
public string MasterProperty { get; set; }
public List<Detail> Details { get; set; }
}
public class Detail
{
public string DetailProperty { get; set; }
}

Resources