I'm trying to populate a Combo with images. It is defined as:
<ComboBox SelectedItem="{Binding SelectedLangComboItem}"
ItemsSource="{Binding Languages}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" />
<TextBlock Text="{Binding Label}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Where the items are the LanguageItem classes:
public class LanguageItem
{
public System.Drawing.Bitmap Image { get; set; }
public string Label { get; set; }
public string Culture { get; set; }
public LanguageItem(System.Drawing.Bitmap image, string label, string culture)
{
Image = image;
Label = label;
Culture = culture;
}
}
Now, in my ViewModel c'tor I do:
_Languages = new ObservableCollection<LanguageItem>();
System.Reflection.Assembly app = System.Reflection.Assembly.GetExecutingAssembly();
System.IO.Stream file;
file = app.GetManifestResourceStream("MyNamespace.Images.FLAG1.gif");
_Languages.Add(new LanguageItem(new Bitmap(file), "ITALIAN", "it-IT"));
file = app.GetManifestResourceStream("MyNamespace.Images.FLAG2.gif");
_Languages.Add(new LanguageItem(new Bitmap(file), "ENGLISH", "en-EN"));
this.SelectedLangItem = _Languages[0];
The images are embedded resources. Here I have two problems:
The images are not displayed;
The Item is not selected, the SelectedLangItem is:
public LanguageItem SelectedLangItem
{
get { return _SelectedLangItem; }
set
{
if (_SelectedLangItem == value)
return;
_SelectedLangItem = value;
this.RaisePropertyChanged("SelectedLangItem");
}
}
Use
new BitmapImage(new Uri("MyNamespace.Images.FLAG1.gif", UriKind.Relative));
as it have to implement ImageSource
And regarding not selected: Property name is "SelectedLangItem" while in xaml SelectedLangComboItem if you did not mistype.
CODE:
this.RaisePropertyChanged("SelectedLangItem");
XAML:
<ComboBox SelectedItem="{Binding SelectedLangComboItem}"
Your problem is that you are trying to bind an Image to the Image.Source property, which is of type ImageSource.
The easiest solution is to add your actual image files into a folder and change the Image property in your class to a string that holds the file path to the image in this format:
/ApplicationName;component/ImageFolderName/ImageName.png
Then you can correctly bind this string (which the Framework will convert into an ImageSource object) to the Image.Source property in your DataTemplate.
Try below xaml code and bind image list into combobox...
<Window.Resources>
<DataTemplate x:Key="cmbTemplate">
<WrapPanel Margin="0 5 0 5" Height="80">
<Image Width="65" Height="65" Stretch="Fill" Source="{Binding Photo}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,15,0"/>
<Label Content="{Binding Name}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="20"/>
</WrapPanel>
</DataTemplate>
</Window.Resources>
<StackPanel HorizontalAlignment="Center">
<Label Content="Dropdown list with Image" HorizontalAlignment="Center" FontSize="30" Margin="20"/>
<ComboBox x:Name="lstwithimg" HorizontalAlignment="Center" VerticalAlignment="Top" ItemTemplate="{StaticResource cmbTemplate}" Height="80" Width="400"/>
</StackPanel>
Check below... for more understanding of live example...
http://www.codescratcher.com/wpf/wpf-combobox-with-image/
Related
I have this ComboBox
<ComboBox x:Name="Renderer" ItemsSource="{Binding RendererItems}"
ItemTemplate="{StaticResource DropDownItemTemplate}" SelectedIndex="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<ei:CallMethodAction TargetObject="{Binding}"
MethodName="RendererItemsSelectionChanged"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
And this Data Template for the items
<DataTemplate x:Key="DropDownItemTemplate">
<StackPanel Orientation="Horizontal">
<UserControl Content="{Binding Icon}" Width="24" Height="24"/>
<TextBlock Text="{Binding Text}" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="10,0"/>
</StackPanel>
</DataTemplate>
And the data comes from:
public ObservableCollection<ComboBoxItemModel> RendererItems { get; set; } = new ObservableCollection<ComboBoxItemModel>();
public MainWindowViewModel()
{
RendererItems.Add(new ComboBoxItemModel() { Icon = new RenderedIcon(), Text = "Rendered" });
RendererItems.Add(new ComboBoxItemModel() { Icon = new WireframeIcon(), Text = "Wireframe" });
RendererItems.Add(new ComboBoxItemModel() { Icon = new ShadedIcon(), Text = "Shaded" });
RendererItems.Add(new ComboBoxItemModel() { Icon = new HiddenLinesIcon(), Text = "Hidden Lines" });
}
The ComboBoxItemModel class is defined like this:
public class ComboBoxItemModel
{
public UserControl Icon { get; set; }
public string Text { get; set; }
}
The first time that I click on the Combo is shown like this:
As you can see the selected item have no Icon
The second time that I click on the Combo is shown like this:
Now the item that I have selected have no Icon. But I want that Combo items always have an Icon.
A UIElement - like your UserControl Icon - can only have one parent element and can therefore only appear once in a visual tree. You should not have a UIElement at all as a view model data item.
In order to model an icon, use a bitmap or a drawing in a DrawingImage:
public class ComboBoxItemModel
{
public ImageSource Icon { get; set; } // assign a DrawingImage
public string Text { get; set; }
}
with
<DataTemplate x:Key="DropDownItemTemplate">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Icon}" Width="24" Height="24"/>
<TextBlock Text="{Binding Text}" .../>
</StackPanel>
</DataTemplate>
An alternative with a UserControl Icon might be to fill a Rectangle with a VisualBrush:
<DataTemplate x:Key="DropDownItemTemplate">
<StackPanel Orientation="Horizontal">
<Rectangle Width="24" Height="24">
<Rectangle.Fill>
<VisualBrush Visual="{Binding Icon}"/>
</Rectangle.Fill>
</Rectangle>
<TextBlock Text="{Binding Text}" .../>
</StackPanel>
</DataTemplate>
The image of the list box item is too large.
I want to make this an item of constant height. Like the picture below.
This is my Code -
xaml:
<ListBox Grid.Row="0" x:Name="listBox" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch" AllowDrop="True" Drop="ListBox_Drop" DragEnter="ListBox_DragEnter" ScrollViewer.VerticalScrollBarVisibility="Visible" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Image Margin="3" Source="{Binding Path}"/>
<TextBlock Margin="3" Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
cs:
class VideoListing
{
public string Name { get; set; }
public string Path { get; set; }
}
List<VideoListing> list = new List<VideoListing>();
public VideoPanel()
{
InitializeComponent();
list.Add(new VideoListing()
{
Name = "hello",
Path = #"C:\Users\johndoe\Desktop\Screenshot.png",
});
listBox.Items.Add(list);
}
You need to set either the Height or the MaxHeight properties on the Image control. Since you say you want a "constant height" then set the height of the image and tell it to scale the source appropriately.
<StackPanel Orientation="Vertical">
<Image Margin="3" Source="{Binding Path}" Height="64" Stretch="Uniform"/>
<TextBlock Margin="3" Text="{Binding Name}"/>
</StackPanel>
use the listView control in your application and use imagelist control to hold many images and set image index in a listview control.
I think it's too simple
I am very new to MVVM and I am stuck with data binding. I have a button on my view page which dynamically creates text boxes but I cannot see how I bind these textboxes to my List in ViewModel.
In my view i have:
<Button x:Name="btWebsite" Grid.ColumnSpan="2" Width="50" Height="50" Click="btWebsite_Click" Margin="23,245,259,202">
<StackPanel x:Name="pnWebsiteButton" Orientation="Horizontal">
<Image x:Name="imgWebsite" Source= "Images/webIcon.jpg" Stretch="Fill" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</StackPanel>
</Button>
<GroupBox x:Name="grpWebsite" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="73,245,0,0" Grid.ColumnSpan="2" Height="51" Width="170" BorderBrush="{x:Null}" BorderThickness="0">
<ScrollViewer x:Name="pnScrollWebsite" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Margin="0,0,0,-6">
<StackPanel x:Name="pnWebsite" Orientation="Vertical" Grid.ColumnSpan="2" HorizontalAlignment="Left" Margin="1,2,0,0" VerticalAlignment="Top" IsEnabled="True">
</StackPanel>
</ScrollViewer>
</GroupBox>
The code behind the button is:
private void btWebsite_Click(object sender, RoutedEventArgs e)
{
var newTextBox = new TextBox();
newTextBox.Text = "type the website address...";
newTextBox.Foreground = Brushes.Gray;
newTextBox.Width = 150;
newTextBox.Name = "txtWebsite" + iWebsites;
pnWebsite.Children.Add(newTextBox);
pnWebsite.RegisterName(newTextBox.Name, newTextBox);
iWebsites++;
}
In my ViewModel i have:
public List<string> Websites
{
get { return _websites; }
set
{
if (value != _websites)
{
_websites = value;
OnPropertyChanged("Websites");
}
}
}
I am struggling to see how I get the website textboxes into the viewmodel list. Thank you for your help
Delete your event handler from the code-behind: btWebsite_Click.
Modify your xaml like this:
<Button x:Name="btWebsite" Grid.ColumnSpan="2" Width="50" Height="50" Command="{Binding AddNewStringCommand}" Margin="23,245,259,202">
<StackPanel x:Name="pnWebsiteButton" Orientation="Horizontal">
<Image x:Name="imgWebsite" Source= "Images/webIcon.jpg" Stretch="Fill" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</StackPanel>
</Button>
<GroupBox x:Name="grpWebsite" VerticalAlignment="Top" HorizontalAlignment="Left" Margin="73,245,0,0" Grid.ColumnSpan="2" Height="51" Width="170" BorderBrush="{x:Null}" BorderThickness="0">
<ScrollViewer x:Name="pnScrollWebsite" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" Margin="0,0,0,-6">
<StackPanel x:Name="pnWebsite" Orientation="Vertical" Grid.ColumnSpan="2" HorizontalAlignment="Left" Margin="1,2,0,0" VerticalAlignment="Top" IsEnabled="True">
<ItemsControl ItemsSource="{Binding Websites}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Mode=TwoWay}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
</GroupBox>
You need to modify your ViewModel also:
public ObservableCollection<string> Websites { get; set; }
public ICommand AddNewStringCommand => new RelayCommand(AddNewString);
private void AddNewString()
{
Websites.Add(string.Empty);
}
Instead of RelayCommand you can use any implementation of ICommand. I use for example MVVMLight.
As you see, the main differences:
Instead of handling the Click event, there is a Command Binding in
the button.
Instead of generating new controls from code behind, there is an
ItemsControl that creates one every time when we have a new
element in the collection.
The new TextBox's Text property is bound to the new element.
Update:
I made a mistake, ObservableCollection is not working directly with the TextBox.
It seems you need something in addition:
public class Website
{
public string Name { get; set; }
}
Modify the ViewModel like this:
public ObservableCollection<Website> Websites { get; set; } = new ObservableCollection<Website>();
public ICommand AddNewStringCommand => new RelayCommand(AddNewString);
private void AddNewString()
{
Websites.Add(new Website {Name = "new website"});
}
And the ItemsTemplate like this:
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel >
<TextBox Text="{Binding Name, Mode=TwoWay}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
i stuck in a problem. i want to bind an image and text data in listpicker wp7. but when i bind image and text into listpicker only text bind. image not bind.
here is my code:
public void loadvehicaltype()
{
List<vehical> listofvehical = new List<vehical>();
listofvehical.Add(new vehical() { CarType= "Any Vehical" });
listofvehical.Add(new vehical() { CarType = "test1", carImage = "Images/car_Images/test_yellow.png" });
listofvehical.Add(new vehical() { CarType = "test2" });
listofvehical.Add(new vehical() { CarType = "Any Vehical" });
this.listPickerVehicalType.ItemsSource = listofvehical;
}
and here is vehical class :
public class vehical
{
public string CarType { get; set; }
public string carImage { get; set; }
}
and here is XAML :
<toolkit:ListPicker x:Name="listPickerVehicalType" Tap="listPickerVehicalType_Tap" SelectionMode="Single" ItemTemplate="{StaticResource ListPickerItemTemplate}" FullModeItemTemplate="{StaticResource ListPickerFullModeItemTemplate}" FullModeHeader="Items" CacheMode="BitmapCache"/>
and
<DataTemplate x:Name="ListPickerItemTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CarType}" Margin="10 0 0 0"/>
<!--<Image Source="{Binding carImage}" Margin="10,0,0,0" Stretch="None" />-->
</StackPanel>
</DataTemplate>
<DataTemplate x:Name="ListPickerFullModeItemTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CarType}" Margin="10,0,0,0"/>
<Image Source="{Binding carImage}" />
</StackPanel>
</DataTemplate>
please help me to sort out this problem. i search this problem but no result found
This is because your image has it's build action set to Resource (Which is the default). you switch it to Content:
right click on your image and set it's build action to Content
Follow these link for more help
Follow these link for more help
I have the need to create a HierarchicalDataTemplate for a TreeView in code-behind.
This is what my XAML looks like:
<DataTemplate x:Key="DetailTemplate">
<StackPanel Orientation="Horizontal">
<Image Height="15" Width="15" Source="{Binding Image}" Margin="0,0,5,0"/>
<TextBlock Text="{Binding Text}" />
</StackPanel>
</DataTemplate>
<HierarchicalDataTemplate x:Key="MasterDetailTemplate"
ItemsSource="{Binding SomeSource}"
ItemTemplate="{StaticResource DetailTemplate}">
<StackPanel Orientation="Horizontal">
<Image Height="15" Width="15" Source="{Binding Image}" Margin="0,0,5,0"/>
<TextBlock Text="{Binding Text}" />
</StackPanel>
</HierarchicalDataTemplate>
This is what i got so far in c#:
Image image = new Image();
image.Name = "image";
image.Height = 15;
image.Width = 15;
Binding imageBinding = new Binding("Image");
BindingOperations.SetBinding(image, Image.SourceProperty, imageBinding);
TextBlock textBlock = new TextBlock();
textBlock.Name = "textBlock";
Binding textBinding = new Binding("Text");
BindingOperations.SetBinding(textBlock, TextBlock.TextProperty, textBinding);
StackPanel stackPanel = new StackPanel();
stackPanel.Orientation = Orientation.Horizontal;
stackPanel.Children.Add(image);
stackPanel.Children.Add(textBlock);
DataTemplate dataTemplate = new DataTemplate();
dataTemplate.DataTemplateKey
I am stuck at the DataTemplateKey.
Is this possible to do in code behind?
Where do i go from here to set the x:Key value?
OK In my comment to your question I specified the code behind way of specifying templates. Now to use / refer them with a key when we add them into ResourceDictionaties, we must add them with a Key.
myWindow.Resources.Add("MasterDetailTemplate", dataTemplate);
Instead of myWindow it can be myParentPanel i.e. any ancestor of your tree view.
But there is one issue..
The Key (i.e. the DataTemplate) doesnt exist at design time. You are creating and adding it at runtime.
So if you are referring this datatemplate then
Either refer the resource after it is are added to the resource dictionary.
e.g.
myWindow.Resources.Add(
"MasterDetailTemplate",
dataTemplate);
myTreeView.ItemTemplate
= myWindow.Resources["MasterDetailTemplate"] as HierarchicalDataTemplate;
Refer the dynamically created data template as DynamicResource in XAML. DynamicResource removes the need of pre-existence of MasterDetailTemplate in any resource dictionary.
<TreeView ItemTemplate="{DynamicResource MasterDetailTemplate}" ... >
....
</TreeView>
Hope this helps.
I do that using resources in XAML:
<DataTemplate x:Key="TreeItemTemplate" DataType="{x:Type a:DriveStatusVar}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding PathName, NotifyOnSourceUpdated = True, NotifyOnTargetUpdated=True, Mode=TwoWay}" FontSize="10" Style="{StaticResource textBlockStyle}" IsEnabled="True"/>
</StackPanel>
</DataTemplate>
<HierarchicalDataTemplate x:Key="TreeModTemplate" DataType="{x:Type a:ModuleGroup}" ItemsSource="{Binding Items}">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource add}" Width="15" Height="15"></Image>
<TextBlock Text="{Binding Name, NotifyOnSourceUpdated = True, NotifyOnTargetUpdated=True, Mode=TwoWay}" Style="{StaticResource textBlockStyle}" />
<TextBlock Text=" [" Foreground="Black" />
<TextBlock Text="{Binding Items.Count}" Foreground="Black" />
<TextBlock Text=" Items]" Foreground="Black" />
</StackPanel>
</HierarchicalDataTemplate>
and use them in code behind where define and create theTreeView object:
TreeView tree = new TreeView();
HierarchicalDataTemplate hdt = (HierarchicalDataTemplate)this.Resources["TreeModTemplat"];
hdt.ItemTemplate = (DataTemplate)this.Resources["TreeItemTemplate"];
tree.ItemTemplate = hdt;
//add itemsource
tree.ItemsSource = modList;
modList is a list of ModuleGroup class with a list Items.
Items is a list of DriveStatusVar class
internal class ModuleGroup : INotifyPropertyChanged, ICloneable
{
private bool _isSelected;
private bool _isExpanded;
private bool _isEdited;
private string _name;
private string _codesysName;
private int _codesysId;
private int _bits;
private int _level;
public ObservableCollection<DriveStatusVar> Items { get; set; }
public ObservableCollection<Alarm> Alarms { get; set; }
public List<string> States { get; set; }
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
OnPropertyChanged("IsSelected");
}
}
and so on... if anybody need more code, please tell me! this is just a piece of them.