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>
Related
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 created an example control that I want to copy as many times as many I will set in code. I want to duplicate entire <ToggleButton> control.
XAML:
<WrapPanel Name="varom">
<ToggleButton Margin="10">
<StackPanel Orientation="Horizontal">
<Label Content="Stop sign" />
<Image Width="16" Source="{Binding appbar_stop}" />
</StackPanel>
</ToggleButton>
<ToggleButton Margin="10">
<StackPanel Orientation="Horizontal">
<Label Content="Stop sign" />
<Image Width="16" Source="{Binding appbar_stop}" />
</StackPanel>
</ToggleButton>
</WrapPanel>
Now I copied one time <ToggleButton> manually, but if I would have just one <ToggleButton> and I want to get second without copying xaml code...
Is it possible to duplicate(copy) <ToggleButton> control using code?
C#:
namespace WpfApplication3
{
public partial class MainWindow : MetroWindow
{
public const int maxButtons = 4; // number of copies for example
public MainWindow()
{
InitializeComponent();
// code add here for example :)
}
}
}
Models:
public class ButtonViewModel
{
public string Caption { get; set; }
}
public class ViewModel
{
public ViewModel()
{
Buttons = new ObservableCollection<ButtonViewModel>
{
new ButtonViewModel { Caption = "Button 1" },
new ButtonViewModel { Caption = "Button 2" },
new ButtonViewModel { Caption = "Button 3" },
};
}
public ObservableCollection<ButtonViewModel> Buttons { get; }
}
XAML:
<ItemsControl ItemsSource="{Binding Buttons}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ToggleButton Margin="10">
<StackPanel Orientation="Horizontal">
<Label Content="{Binding Caption}" />
<Image Width="16"/>
</StackPanel>
</ToggleButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
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'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/