Combobox selection sequence for images - c#

I'm a little noobish so sorry if this is really simple...
I have ~120 pictures and I would like to be able to select and display one of those pictures when the name in the combobox corresponds to that picture. I would like to know how to populate the combobox with the name of each picture and select a picture from the box without making 120 "if" statements? Each image has it's own filename in the project.Properties.Resources folder
Also, if there's a way to rename 120 pictures really quickly, that would save me a lot of time but it's fine if i just have to do it by hand.
The form is WPF and I'm using Visual studio 2012 Express

You can create a Model to hold your image data and populate a ObservableCollection<T> of that model, Then we can bind that collection to the ComboBox and set the ComboBox selectedItem to a Image control
Here is an example:
Code:
namespace WpfApplication14
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<MyImage> _images = new ObservableCollection<MyImage>();
private MyImage _selectedImage;
public MainWindow()
{
InitializeComponent();
// Add image files to collection
foreach (var image in Directory.GetFiles(#"C:\your image directory"))
{
// set name and path in model
Images.Add(new MyImage { Path = image, Name = System.IO.Path.GetFileNameWithoutExtension(image) });
}
}
public ObservableCollection<MyImage> Images
{
get { return _images; }
set { _images = value; }
}
public MyImage SelectedImage
{
get { return _selectedImage; }
set { _selectedImage = value; NotifyPropertyChanged("SelectedImage"); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
public class MyImage
{
public string Name { get; set; }
public string Path { get; set; }
}
}
Xaml:
<Window x:Class="WpfApplication14.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Name="UI">
<StackPanel DataContext="{Binding ElementName=UI}">
<TextBlock Text="Images" />
<ComboBox ItemsSource="{Binding Images}" SelectedItem="{Binding SelectedImage}" DisplayMemberPath="Name"/>
<TextBlock Text="Selected Image" />
<Image Source="{Binding SelectedImage.Path}" />
</StackPanel>
</Window>
Result:

Well WPF memories are really rusty but as a generalization, you need to know where the selected image in in List. What you can do is keep track of index/positoin of each image in list in a dictionary:
private imageIndices=new Dictionary<string, int>();
store indices:
imageIndices[<IMAGE_NAME>] = <INDEX_OF_IMAGE>;
get name of image from dropdown and get where that image is from dictionary:
var n=<IMAGE_NAME>;
list.Select(imageIndices[<IMAGE_NAME>]);//use actual method name to select

Related

On NavigationView page change, data binding is lost

Changing page through the NavigationView control causes some data bindings to fail/be lost.
data model:
public class Flashpoint
{
private string name;
private string description;
private string image;
public string Name
{
get { return name; }
set { name = value; }
}
public string Description
{
get { return description; }
set { description = value; }
}
public string Image
{
get { return image; }
set { image = value; }
}
}
page xaml:
<Page
x:Class="Braytech_3.Views.MainPage"
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:local="using:Braytech_3.Views"
xmlns:data="using:Braytech_3.Models"
Style="{StaticResource PageStyle}"
mc:Ignorable="d">
<Grid x:Name="ContentArea">
<StackPanel Height="400" HorizontalAlignment="Left" VerticalAlignment="Top">
<Image HorizontalAlignment="Center" VerticalAlignment="Center" Source="{x:Bind CurrentFlashpoint.Image, Mode=OneWay}" Stretch="UniformToFill"/>
<TextBlock Text="{x:Bind CurrentFlashpoint.Name, Mode=OneWay}" />
</StackPanel>
page cs:
namespace Braytech_3.Views
{
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
Flashpoint CurrentFlashpoint { get; set; }
public MainPage()
{
InitializeComponent();
Render();
}
public event PropertyChangedEventHandler PropertyChanged;
private void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
{
if (Equals(storage, value))
{
return;
}
storage = value;
OnPropertyChanged(propertyName);
}
private void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
private async void Render()
{
StorageFolder tempFolder = ApplicationData.Current.TemporaryFolder;
StorageFile APIData = await tempFolder.GetFileAsync("APIData.json");
string json = await FileIO.ReadTextAsync(APIData);
Universal request = JsonConvert.DeserializeObject<Universal>(json);
foreach (var challenge in request.response.data.challenges)
{
if (challenge.type == "flashpoint")
{
CurrentFlashpoint = new Models.Flashpoint
{
Name = challenge.name,
Description = challenge.description,
Image = $"/Assets/Images/{ challenge.slug }.jpg"
};
}
}
}
}
}
Omitted from the above code excerpts is an ObservableCollection that is bound to the pivot control below the image control. It works as expected. Vendors page also uses an ObservableCollection. As I am only trying to bind single items (textblock, image), I wasn't sure how I could use an ObservableCollection and if I even should attempt to as to me it's the equivalent of an array of items where as I'm trying to bind a single item.
Using the live tree inspector I was able to inspect the image control, before and after the data binding is lost, but it didn't lead me to an answer as to why.
Why does it lose its binding and how can I fix it?
The better way is that you could set NavigationCacheMode="Required" for MainPage to avoid repeat loading.
The page is cached and the cached instance is reused for every visit regardless of the cache size for the frame.
This is official document that you could refer.

Databind the soure of ImageBrush inside ellipse inside a button

I want to create a circle "play" button.
I want to use 2 photos. 1 is the default pic called:"PlayButton.png"
and another that should appear after the user clicked on the button called: "PlayButtonPressed.png" both inside Images folder.
I tried to use a simple databinding for the ImageSource of the ImageBrush to check this.
However the Inotifychange propery stays null. and no pictures is looked. not when the program run and not when clicking on the empty button.
how can I do that with data binding to controll the Image Source.
here is my code:
XAML:
<Window x:Class="COMSimulator.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Converters="clr-namespace:COMSimulator"
<Button x:Name="btnStart" Grid.Column="0" Grid.Row="2"
HorizontalAlignment="Center" VerticalAlignment="Center" Width="50"
Height="50" Click="btnStart_Click">
<Button.Template>
<ControlTemplate>
<Ellipse Height="50" Width="50">
<Ellipse.Fill>
<ImageBrush ImageSource="{Binding Path=ImagePlayButton}"></ImageBrush>
</Ellipse.Fill>
</Ellipse>
</ControlTemplate>
</Button.Template>
</Button>
</Window >
C#:
namespace COMSimulator
{
public partial class MainWindow : Window
{
public viewModeImage VMI { get; set; }
public MainWindow()
{
InitializeComponent(); //init componenets
VMI = new viewModeImage();
DataContext = this;
VMI.ImagePlayButton = Consts.IMAGE_PLAY_BUTTON;
}
}
}
C# viewModel:
namespace COMSimulator
{
public class viewModeImage:INotifyPropertyChanged
{
private string _imagePlayButton;
/// <summary>
/// this method init all window Items to relavent Data
/// </summary>
public string ImagePlayButton
{
get
{
return _imagePlayButton;
}
set
{
_imagePlayButton = value;
OnProperyChanged("ImagePlayButton");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnProperyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
C# Const Value
public static class Consts
{
public const string IMAGE_PLAY_BUTTON =#"Images\PlayButton.png";
public const string IMAGE_PLAY_BUTTON_PRESSED = #"Images\PlayButtonPressed.png";
}
Try to set the DataContext of the window to itself:
public MainWindow()
{
InitializeComponent(); //init componenets
ImagePlayButton= #"Images\PlayButton.png";
DataContext = this;
}
The Path of a Binding refers to a property name of the DataContext of the element. This means that you need to set the DataContext to the class where the ImagePlayButton property is defined for your binding to work.
Edit: Since the ImagePlayButton property is defined in another class, you should set the DataContext to an instance of this one:
public MainWindow()
{
InitializeComponent(); //init componenets
VMI = new viewModeImage();
VMI.ImagePlayButton = Consts.IMAGE_PLAY_BUTTON;
this.btnStart.DataContext = VMI;
}

What System.Windows UIElement does skype use for its 'Contact List'?

Hey so I was wondering what UIElement does skype use for its Contact List in order to display additional details within each ListItem (such as Status Updates, Avatars, Online Status and so forth)?
(source: iforce.co.nz)
As far as I know the regular System.Windows.Forms.ListBox only lets you display a single line of text to represent that Object.
(source: iforce.co.nz)
I'm looking to recreate something similar but for a different purpose, but I haven't been able to find much on google (So that's why I'm seeing if anyone here has experience modifying the design of a ListBox, to gain a better perspective over each detail).
Thanks
Here is a very basic example of creating a custom Datatemplate for WPF.
First you create your Model with all the properties you want to be displayed, then bind a list of them to your ListBox. Then you can create a DataTemplate this is basically a xaml(visual) representation of your Model, you can make it look however you want and you can use any of the properties from your Model in the DataTemplate.
Example:
Window code:
public partial class MainWindow : Window
{
private ObservableCollection<MyListBoxItemModel> _listBoxItems = new ObservableCollection<MyListBoxItemModel>();
public MainWindow()
{
InitializeComponent();
ListBoxItems.Add(new MyListBoxItemModel { Title = "Item 1", Image = new BitmapImage(new Uri("http://icons.iconarchive.com/icons/custom-icon-design/mini/32/Search-icon.png")) });
ListBoxItems.Add(new MyListBoxItemModel { Title = "Item 2", Image = new BitmapImage(new Uri("http://icons.iconarchive.com/icons/custom-icon-design/mini/32/Search-icon.png")) });
ListBoxItems.Add(new MyListBoxItemModel { Title = "Item 3", Image = new BitmapImage(new Uri("http://icons.iconarchive.com/icons/custom-icon-design/mini/32/Search-icon.png")) });
}
public ObservableCollection<MyListBoxItemModel> ListBoxItems
{
get { return _listBoxItems; }
set { _listBoxItems = value; }
}
}
Model:
public class MyListBoxItemModel : INotifyPropertyChanged
{
private string _title;
private string _line2 = "Line2";
private BitmapImage _image;
public string Title
{
get { return _title; }
set { _title = value; NotifyPropertyChanged("Title"); }
}
public string Line2
{
get { return _line2; }
set { _line2 = value; NotifyPropertyChanged("Line2"); }
}
public BitmapImage Image
{
get { return _image; }
set { _image = value; NotifyPropertyChanged("Image"); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string p)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(p));
}
}
}
Xaml:
<Window x:Class="WpfApplication7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication7"
Title="MainWindow" Height="351" Width="464" Name="UI" >
<Window.Resources>
<!-- The tempate for MyListBoxItemModel -->
<DataTemplate DataType="{x:Type local:MyListBoxItemModel}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" />
<StackPanel>
<TextBlock Text="{Binding Title}" FontWeight="Medium" />
<TextBlock Text="{Binding Line2}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding ElementName=UI, Path=ListBoxItems}" />
</Grid>
</Window>
This is just a simple example with an Image and some text, but it should get you started, Just modify the DataTemplate and Model how you want to display the snp code data
Result:

load URL into WebBrowser with MVVM

I'm makeing an app where you have a listbox in the buttom with a logo of different websites, and a WebBrowseron the top. The idea is that when you press on a logo, the webBrowser load the corresponding page. I already make this work, but I want to remake the app with MVVM to make it better. I've made the listbox with all the logos, but I dont know how to load the URL onto the WebBrowser when I click on the logo.
Not 100% sure if this will work on Phone7 but worth a shot...
Fist off the WebBrowser Source property is not bindable as its not a DependancyProperty so you will have to make a helper class to create an AttachedProperty to help with the binding.
Then you can link your ListBox SelectedItem to the new LinkSource property using the Property that contains the actual link from your ListBoxItem.
Example:
Xaml:
<Window x:Class="WpfApplication8.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication8"
Title="MainWindow" Height="233" Width="405" Name="UI">
<StackPanel Orientation="Horizontal" DataContext="{Binding ElementName=UI}">
<ListBox x:Name="listbox" ItemsSource="{Binding Links}" Width="100" DisplayMemberPath="Name"/>
<WebBrowser local:WebBrowserHelper.LinkSource="{Binding ElementName=listbox, Path=SelectedItem.Site}" Width="200"/>
</StackPanel>
</Window>
Code:
public partial class MainWindow : Window
{
private ObservableCollection<Link> _links = new ObservableCollection<Link>();
public MainWindow()
{
InitializeComponent();
Links.Add(new Link { Name = "StackOverflow", Site = new Uri("http://stackoverflow.com/") });
Links.Add(new Link { Name = "Google", Site = new Uri("http://www.google.com/") });
}
public ObservableCollection<Link> Links
{
get { return _links; }
set { _links = value; }
}
}
// ListBox item
public class Link
{
public string Name { get; set; }
public Uri Site { get; set; }
}
// helper calss to create AttachedProperty
public static class WebBrowserHelper
{
public static readonly DependencyProperty LinkSourceProperty =
DependencyProperty.RegisterAttached("LinkSource", typeof(string), typeof(WebBrowserHelper), new UIPropertyMetadata(null, LinkSourcePropertyChanged));
public static string GetLinkSource(DependencyObject obj)
{
return (string)obj.GetValue(LinkSourceProperty);
}
public static void SetLinkSource(DependencyObject obj, string value)
{
obj.SetValue(LinkSourceProperty, value);
}
// When link changed navigate to site.
public static void LinkSourcePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var browser = o as WebBrowser;
if (browser != null)
{
string uri = e.NewValue as string;
browser.Source = uri != null ? new Uri(uri) : null;
}
}
}
Result:
Your question are actually two questions.
There're several ways to pick up clicks from listbox. Most basic one is <Listbox SelectedItem="{Binding selectedItem,mode=TwoWay}" ...
To set the web browser's URL, you could implement INotifyPropertyChanged in your VM, declare public Uri browserUri { get; private set; } in your WM, be sure to raise PropertyChanged when you change the property, and in XAML <WebBrowser Source="{Binding browserUri}" />

WPF List of Groups of Controls Databound to List of Custom Class?

I'm still somewhat new to WPF (only done a few small projects with it). I'm trying to make a repeating group of controls (user can add/remove these groups), databound to a custom class. Example UI:
([UserButton1] [UserButton2]) <--each of these () is a separate group of buttons
([Cheese] [Wine] )
([Wallace] [Gromit] )
[Add] <--this button can add more groups
databound to a list of a class like this (pseudocode):
class UserButtons {
string UserButton1 = "UserButton1"
string UserButton2 = "UserButton2"
}
such as
List<UserButtons> = {
[0]: UserButton1, UserButton2
[1]: Cheese, Wine
[2]: Wallace, Gromit
}
I know this is the sort of thing WPF was created to do, but I can't quite figure out exactly how to go about it.
Should I use some sort of ListView? Would a DataTemplate help? A StackPanel sounds OK, but it doesn't have databinding for a list...or does it? And I'm not even sure how to make databinding work for the groups of buttons like indicated above (if that even made sense to you...sorry for the bad example). Does anyone have any insight on this problem?
I searched to try to find a question pertaining to this and didn't see one, perhaps because I wasn't sure what to search for. So, sorry if it's an unintended dupe.
I'm not entirely sure what you're looking for but I hope the example below helps. I used an ItemsControl whose ItemsSource is set to the collection of UserButtons. Its ItemTemplate property is set to a StackPanel that shows two buttons, the Content property of each is bound to properties in UserButtons.
XAML:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication3"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
</Window.Resources>
<StackPanel Orientation="Vertical">
<ItemsControl x:Name="itemsControl" Background="LightBlue">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Content="{Binding Button1}" Width="100"/>
<Button Content="{Binding Button2}" Width="100"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Button Width="50" Click="Button_Click">Add</Button>
</StackPanel>
</Window>
Code-Behind:
public partial class MainWindow : Window
{
ObservableCollection<UserButtons> oc;
public MainWindow()
{
InitializeComponent();
oc = new ObservableCollection<UserButtons>()
{
new UserButtons() { Button1="UserButton1", Button2 = "UserButton2"},
new UserButtons() { Button1="Cheese", Button2 = "Wine"},
new UserButtons() { Button1="Wallace", Button2 = "Gromit"},
};
this.itemsControl.ItemsSource = oc;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
oc.Add(new UserButtons() { Button1 = "NewButton1", Button2 = "NewButton2" });
}
}
public class UserButtons : INotifyPropertyChanged
{
private string button1;
public string Button1
{
get { return this.button1; }
set
{
this.button1 = value;
this.OnPropertyChanged("Button1");
}
}
private string button2;
public string Button2
{
get { return this.button2; }
set
{
this.button2 = value;
this.OnPropertyChanged("Button2");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
#endregion
}

Categories

Resources