Basically, when a user clicks a button I would like to add a list of the names of the currently running applications with their icon next to them within a ComboBox. I know how to get my list of applications and my icons but am unsure how to link everything together. My XAML for the ComboBox currently looks like the following:
<ComboBox x:Name="dial1AppSelection" Grid.Column="3" Grid.Row="4" MinHeight="25" Height ="25" MaxHeight="35" MinWidth="120" Margin="4,0,0,0" SelectionChanged="dial1AppSelection_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Height="20" Source="???" />
<TextBlock ><Run Text="???" /></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Add to your combobox
ItemsSource="{Binding YourCollection}"
Create class for your objects:
public class MyProcess
{
public ImageSource Image { get; set; }
public string Text { get; set; }
}
Add such code to your MainWindow.xaml.cs
public ObservableCollection<MyProcess> YourCollection { get; set; }
public MainWindow()
{
InitializeComponent();
YourCollection = new ObservableCollection<MyProcess>();
YourCollection.Add(new MyProcess() { Image ="image1", Text = "txt1"});
DataContext = this;
}
Insert fields names to your xaml code:
Source="{Binding Path=Image}"
Text="{Binding Path=Text}"
Related
This is my ListView:
<ListView ItemsSource="{Binding ModuleList}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!--<Image Source="{Binding ModuleImage}" Stretch="UniformToFill"/>-->
<TextBlock Text="{Binding ModuleName}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This is the code in WPF (MVVM):
public ItemListViewVM() : base()
{
ModuleList = new List<Module>();
modulLoader.LoadAllModules();
tempModulList = modulLoader.GetAllModules();
foreach (var module in tempModulList)
{
ModuleImage = module.ModuleImage;
ModuleName = module.Name;
ModuleList.Add(module);
}
}
Long story short: The List tempModulList contains Objects of type Module, which has an ImageSource Image and a string Name. Then the ModuleList gets one item after another. When I uncomment the Image in xaml, you can see it. But the TextBlock won't show up no matter what. I checked the string module.Namefor every item, it is not empty.
EDIT: Add Module Class
The Module Class just contains Name and Image:
public class Module
{
public ImageSource ModuleImage { get; set; }
public string Name { get; set; }
}
The Object gets created by deserializing a Json
The Bindings in the ItemTemplate use the properties of the data item class as their source properties. Hence you should write
Text="{Binding Name}"
instead of
Text="{Binding ModuleName}"
Unless you set the View property of a ListView (to e.g. a GridView) you could also better use a ListBox, which is the base class of ListView, and simpler:
<ListBox ItemsSource="{Binding ModuleList}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ModuleImage}"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Initializing the ModuleList property in the view model constructor would be as simple as this:
public ItemListViewVM()
{
modulLoader.LoadAllModules();
ModuleList = modulLoader.GetAllModules();
}
Alrighty, so I have, as I said, a ComboBox within a ListBox. These are both controls (WPF project using C# in Visual Studio 2010 and MVVM).
I can create them all good and well.
The ListBox contains an ObservableCollection of something called IntWrapper, which just contains and int.
The ComboBox is loaded with an ObservableCollection of something called MissionViewModel, which is just a class that contains a few basic data types.
So the ItemSource for the ListBox and the ComboBox are different.
I can add and items to the ListBox with a button, which just adds a new IntWrapper to the ObservableCollection. Visually this gives me a new ComboBox, which is populated.
What I can't figure out is how to get one of the properties of MissionViewModel to go to the property in the IntWrapper when I select it.
Previously I just used a TextBox in the ListBox, which looked like this:
<ListBox x:Name="lbMissionsToGive" ItemsSource="{Binding MissionsToGive}" SelectedItem="{Binding SelectedMissionToGive}" ContextMenu="{StaticResource RemoveMissionToGiveMenu}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="2" BorderBrush="LightBlue" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="2" CornerRadius="5,5,5,5">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="1">Mission ID: </TextBlock>
<TextBox Margin="1" Text="{Binding Int, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My (non working) attempt whereby I replace the TextBox with the ComboBox is this:
<ListBox x:Name="lbMissionsToGive" ItemsSource="{Binding MissionsToGive}" SelectedItem="{Binding SelectedMissionToGive}" ContextMenu="{StaticResource RemoveMissionToGiveMenu}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="2" BorderBrush="LightBlue" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="2" CornerRadius="5,5,5,5">
<StackPanel Orientation="Horizontal">
<ComboBox DisplayMemberPath="MissionNameAndID" SelectedValuePath="Int" ItemsSource="{Binding MissionListViewModel.MissionVMs, Source={StaticResource Locator}}"></ComboBox>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I had thought SelectedValuePath would be the thing I wanted, but this so far doesn't seem to work (perhaps I'm using it incorrectly).
Any assistance would be appreciated.
Bind the SelectedValue property of the ComboBox to the Int property of the IntWrapper:
<ComboBox DisplayMemberPath="MissionNameAndID" SelectedValuePath="Int" SelectedValue="{Binding Int}"
ItemsSource="{Binding MissionListViewModel.MissionVMs, Source={StaticResource Locator}}" />
This should work provided that the IntWrapper.Int property has a public setter and that the Int property of the MissionViewModel is of the same type as the Int property of the IntWrapper.
I tried to create a solution for your problem based on your description. To help you more qualified, we would need more information about the MissionViewModel and the Properties contained in it.
I suppose, your Binding does not point to the correct ViewModel. I tried to recreate what you describe below and in my case, the combobox is filled with the Name Property of the MissionVm class.
This is the XAML. Here I changed the ItemsSource Binding to directly point to the ObservableCollection of the DataContext of the parent window.
<ListBox x:Name="lbMissionsToGive" ItemsSource="{Binding MissionsToGive}" SelectedItem="{Binding SelectedMissionToGive}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="2" BorderBrush="LightBlue" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="2" CornerRadius="5,5,5,5">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding }"></TextBlock>
<ComboBox Margin="20" Width="50" ItemsSource="{Binding DataContext.MissionVMs, RelativeSource={RelativeSource AncestorType=Window}}" DisplayMemberPath="Name"></ComboBox>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And this is the ViewModel based on your description:
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
var vm1 = new MissionVM { Id = 1, Name = "111"};
var vm2 = new MissionVM { Id = 2, Name = "222" };
var vm3 = new MissionVM { Id = 3, Name = "333" };
MissionVMs = new ObservableCollection<MissionVM> { vm1, vm2, vm3};
MissionsToGive = new ObservableCollection<int> {1, 2, 3};
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public ObservableCollection<int> MissionsToGive { get; set; }
public int SelectedMissionToGive { get; set; }
public ObservableCollection<MissionVM> MissionVMs { get; set; }
}
public class MissionVM
{
public int Id { get; set; }
public string Name { get; set; }
}
This is the Output:
I hope this helps. If i misunderstood you, please give further explanation of the problem.
My model:
public class MyMessageModel
{
public string DisplaySender { get; set; }
//how does the below observable collection needs to be changed ,
//if I want to add another field to itemssource template.
//e.g. public DateTime Timestamp { get; set; }
public ObservableCollection<string> MessagesExchanged { get; set; }
public string NewMessage { get; set; }
}
Chat.xaml:
<TextBlock Name="lblFromUserName" Text="{Binding DisplaySender ,Mode=TwoWay}" Height="65" Style="{StaticResource PhoneTextNormalStyle}" FontSize="35"/>
<ItemsControl ItemsSource="{Binding Path=MessagesExchanged}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ????,Mode=TwoWay}" />
<TextBlock Text="{Binding Path=Timestamp}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Grid.Row="1"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl
<StackPanel Orientation="Horizontal" Grid.Row="1">
<TextBox Grid.Column="0" Name="txtNewMessage" Text="{Binding NewMessage,Mode=TwoWay}" Margin="0,0,0,0" Width="350"/>
<Button Grid.Column="1" Command="{Binding SendClickCommand,Mode=TwoWay}" Name="btnSend" Content="Send" Width="100" />
</StackPanel>
Chat.xaml.cs looks like below:
public class Chat: PhoneApplicationPage
{
private MyMessageViewModel _MyMessageViewModel;
public Conversation()
{
InitializeComponent();
_MyMessageViewModel = new MyMessageViewModel();
this.DataContext = _MyMessageViewModel;
}
}
My ViewModel MyMessageViewModel looks like below:
public System.Windows.Input.ICommand SendClickCommand
{
get
{
return new DelegateCommand((o) =>
{
Task.Factory.StartNew(() =>
{
//loop through the selected items and clear everything
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
try
{
//DO YOUR WORK HERE: TAKE THE NEW MESSAGE AND APPEND IT TO THE MESSAGES EXCHANGED
}
catch (Exception)
{
throw;
}
});
});
});
}
}
Now when user is in the above view called Chat.xaml (user will come to this page from Home page) i want to load it with the DisplaySender value on the top which will be fixed during the entire conversation.Value for this field be passed as navigation parameter from the home page.
And everytime user clicks on the Send button , in the SendClickCommand only update the MessagesExchanged collection by adding the new message from the txtNewMessage field and later clear this field.
I have two questions here:
When user first comes to the Chat.xaml how do i bind the data for the three fields e.g. DisplaySender(non empty value will be passed as navigation parameter ),MessagesExchanged(initially this would be empty when initiating the new conversation, otherwise it will have a non empty value from the navigation parameter) and NewMessage (initially this would be empty always).
Secondly in SendClickCommand notified property how do i take the text from txtNewMessage and update the ObservableCollection MessagesExchanged and at the end clear the value of txtNewMessage .And how to bind the values of MessagesExchanged to the datatemplate textblock field ?
I guess you are trying to pass Object of Class MyMessageModel while navigating from HomePage to ChatPage.
So define a property
private MyMessageModel currentMessageModel;
public MyMessageModel CurrentMessageModel
{
get { return currentMessageModel; }
set { currentMessageModel = value; }
}
and in OnNavigatedTo method of ChatPage set
CurrentMessageModel=PassedObjectOfMessageModel
xaml:
<TextBlock Name="lblFromUserName" Text="{Binding CurrentMessageModel.DisplaySender ,Mode=TwoWay}" Height="65" Style="{StaticResource PhoneTextNormalStyle}" FontSize="35"/>
<ItemsControl ItemsSource="{Binding Path=CurrentMessageModel.MessagesExchanged}">
//No need for data template as collection only contains string
<ItemsControl
<StackPanel Orientation="Horizontal" Grid.Row="1">
<TextBox Grid.Column="0" Name="txtNewMessage" Text="{Binding NewMessage,Mode=TwoWay}" Margin="0,0,0,0" Width="350"/>
<Button Grid.Column="1" Command="{Binding SendClickCommand,Mode=TwoWay}" Name="btnSend" Content="Send" Width="100" />
</StackPanel>
//C#
CurrentMessageModel.MessagesExchanged.Add(txtNewMessage.Text);
and you donot need any text block to show the ObservableCollection as your collection only contains string so just by setting the ItemsSource to the collection the data would be displayed.
I have a listbox which is bound to a list of Currencies items. Currency is a class
public class Currency
{
public string code { get; set; }
public string countryName { get; set; }
public string imgUrl { get; set; }
public string infoLink { get; set;} }
}
A list box is bound to a list of Currencies Objects and each item in this listbox is a stackpanel of an image and textblock
I want to bind the SelectedItem property to a property in the Code-behind to keep up
<ListBox Name="sCurrencyLB" Margin="10,0,0,0" Width="Auto" Height="180"
IsEnabled="{Binding IsChecked, ElementName=LiveTilesToggleBtn}"
SelectedItem="{Binding STileCurrency, Mode=TwoWay,
Source={StaticResource livetilemanager}}"
ItemsSource="{Binding SCurrencyList}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<TextBlock Name="scountryNametb" Width="50" Text="{Binding code}"
VerticalAlignment="Center" HorizontalAlignment="Right"/>
<Image Source="{Binding imgUrl}" Height="50" Width="50"
HorizontalAlignment="Left" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Code of the property that should beind the selected item in the listbox
private Currency sTileCurrency;
public Currency STileCurrency
{
get
{
return appSettings.GetValueorDefault<Currency>("STileCurrency", null);
}
set
{
if (appSettings.AddOrUpdateValue("STileCurrency", value))
{
settings.Save();
}
}
}
Note : I created an instance of Class containing the property inside XAML
Follow MVVM Pattern(pretty) that's what you need
try this:
befor InitializeComponent(); in your contractor of window add this:
this.DataContext = this;
so bind the SelectedItem like this
SelectedItem="{Binding STileCurrency,Mode=TwoWay}
What you have should work if livetilemanager here:
Source={StaticResource livetilemanager}}
Has a property on it:
SCurrencyList
Does it? If SCurrencyList is a property in your code-behind - since the code-behind is the default DataContext - you do not need to specify a Source for you SelectedItem binding.
By the way to see binding errors keep an eye on the Debug Window in VS while debugging.
Incidentally in C# it typical to name properties with capital first letter, e.g.:
public string Code {get;set;}
I have a class with a list of images in it.
public class RSSClass
{
public string Title { get; set; }
public string Summary { get; set; }
public string PubDate { get; set; }
public List<ImageData> ImagePath { get; set; }
public class ImageData
{
public Uri ImageLocation
{
get;
set;
}
}
}
Hers the XAML
<ListBox Name="lstRSS">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<StackPanel.Resources>
</StackPanel.Resources>
<TextBlock Text="{Binding Path=Title}"> </TextBlock>
<TextBlock Text="{Binding Path=PubDate}"></TextBlock>
<TextBlock Text="{Binding Path=Summary}"></TextBlock>
<ListBox x:Name="ImageListBox" ItemsSource="{Binding ImagePath}">
<DataTemplate>
<Image x:Name="image1" Source="{Binding}" MaxHeight="80" MaxWidth="120" Margin="0"></Image>
</DataTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The inner list box, ImageListBox, binds and shows the string value of the Uri. Im just not sure what to bind the image in the inner list box, image1, to?
Any help much appreciated.
Regards
Ross
You are missing <ListBox.ItemTemplate> around your <DataTemplate>. This confuses ListBox, so it thinks it is actualy an item, not a template.
Once you implement #Euphoric's resolution, bind the image1's source to ImageLocation. Example:
<Image x:Name="image1" Source="{Binding ImageLocation}" MaxHeight="80" MaxWidth="120" Margin="0"></Image>