I have created a very basic wpf application that I want to use to record time entries against different projects.
I havent used mvvm for this as I think its an overkill.
I have a form that contains a combobox and a listbox. I have created a basic entity model like this
What I am trying to do is bind the combobox to Project and whenever I select an item from the combobox it updates the listview with the available tasks associated with that project.
This is my xaml so far. I dont have any code behind as I have simply clicked on that Data menu and then datasources and dragged and dropped the items over. The application loads ok and the combobox is been populated however nothing is displaying in the listbox.
Can anyone tell me what I have missed?
<Window.Resources>
<CollectionViewSource x:Key="tasksViewSource" d:DesignSource="{d:DesignInstance l:Task, CreateList=True}" />
<CollectionViewSource x:Key="projectsViewSource" d:DesignSource="{d:DesignInstance l:Project, CreateList=True}" />
</Window.Resources>
<Grid DataContext="{StaticResource tasksViewSource}">
<l:NotificationAreaIcon
Text="Time Management"
Icon="Resources\NotificationAreaIcon.ico"
MouseDoubleClick="OnNotificationAreaIconDoubleClick">
<l:NotificationAreaIcon.MenuItems>
<forms:MenuItem Text="Open" Click="OnMenuItemOpenClick" DefaultItem="True" />
<forms:MenuItem Text="-" />
<forms:MenuItem Text="Exit" Click="OnMenuItemExitClick" />
</l:NotificationAreaIcon.MenuItems>
</l:NotificationAreaIcon>
<Button Content="Insert" Height="23" HorizontalAlignment="Left" Margin="150,223,0,0" Name="btnInsert" VerticalAlignment="Top" Width="46" Click="btnInsert_Click" />
<ComboBox Height="23" HorizontalAlignment="Left" Margin="70,16,0,0" Name="comProjects" VerticalAlignment="Top" Width="177" DisplayMemberPath="Project1" ItemsSource="{Binding Source={StaticResource projectsViewSource}}" SelectedValuePath="ProjectID" />
<Label Content="Projects" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" IsEnabled="False" />
<Label Content="Tasks" Height="28" HorizontalAlignment="Left" Margin="16,61,0,0" Name="label2" VerticalAlignment="Top" />
<ListBox Height="112" HorizontalAlignment="Left" Margin="16,87,0,0" Name="lstTasks" VerticalAlignment="Top" Width="231" DisplayMemberPath="Task1" ItemsSource="{Binding Path=ProjectID, Source=comProjects}" SelectedValuePath="TaskID" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="101,224,0,0" Name="txtMinutes" VerticalAlignment="Top" Width="42" />
<Label Content="Mins to Insert" Height="28" HorizontalAlignment="Left" Margin="12,224,0,0" Name="label3" VerticalAlignment="Top" />
<Button Content="None" Height="23" HorizontalAlignment="Left" Margin="203,223,0,0" Name="btnNone" VerticalAlignment="Top" Width="44" />
</Grid>
You set the DataContext in the Grid, so just change your ItemsSource as indicated below.
<Grid DataContext="{StaticResource tasksViewSource}">
<ListBox Height="112"
HorizontalAlignment="Left"
Margin="16,87,0,0"
Name="lstTasks"
VerticalAlignment="Top"
Width="231"
DisplayMemberPath="Task1"
ItemsSource="{Binding}"
SelectedValuePath="TaskID" />
</Grid>
You'll also want to filter the task list, to do that just change the generated code.
Here is an example I hacked together.
You can toggle the value using the SelectionChanged event from your ComboBox.
private System.Data.Objects.ObjectQuery<Models.Task> GetTasksQuery(Models.StackoverflowEntities stackoverflowEntities)
{
// get the selected item
int id = (int)cboProjects.SelectedValue;
System.Data.Objects.ObjectQuery<CollectionViewSourceEF.Models.Task> tasksQuery = stackoverflowEntities.Tasks.Where(task => task.ProjectID == id) as ObjectQuery<Task>;
return tasksQuery;
}
Related
I am working with a Windows Phone 8.1 Silverlight application that has instances of various controls on the page, buttons, check boxes, radio buttons, etc. and a slider.
Each control has an event handler added as follows, this example is specific to the slider, but other controls just replace the type of control and the actual event handled:
static void instrumentSlider(Slider slider)
{
Logger.Logger.LogMessage("instrumentSlider() - Called for: [" + slider + "]");
slider.ManipulationCompleted -= new EventHandler<ManipulationCompletedEventArgs>(slider_ManipulationCompleted);
slider.ManipulationCompleted += new EventHandler<ManipulationCompletedEventArgs>(slider_ManipulationCompleted);
}
static void slider_ManipulationCompleted(object sender, ManipulationCompletedEventArgse)
{
try
{
Logger.Logger.LogMessage("slider_ManipulationCompleted() - Called for: [" + sender + "]");
if (sender is Slider)
{
Slider slider = (Slider)sender;
// Do stuff...
}
}
catch (Exception ex)
{
Logger.Logger.LogException(ex);
}
}
I can download the app to the phone using visual Studio 2013 and everything works as expected, when I press buttons or move the slider I see the logging messages I expect to see.
At some point I accidentally pressed the camera button on the phone and my app was deactivated and the camera app activated. I switched back to my app and all the controls except the slider continue to produce events!
What am I missing here? I've tried several events for the slider, manipulation completed, lost focus, value changed, and they all stop being delivered after the app is reactivated, but events from all other controls are still being delivered.
Updated to include an XAML fragment defining the controls:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Slider Height="84" HorizontalAlignment="Left" Margin="37,243,0,0" Name="slider1" VerticalAlignment="Top" Width="383" />
<Button Content="Button" Height="72" HorizontalAlignment="Left" Margin="27,18,0,0" Name="button1" VerticalAlignment="Top" Width="160" Click="button1_Click" RenderTransformOrigin="0.531,-0.222" />
<CheckBox Content="CheckBox" Height="72" HorizontalAlignment="Left" Margin="241,17,0,0" Name="checkBox1" VerticalAlignment="Top" RenderTransformOrigin="0.509,0.181" />
<HyperlinkButton Content="HyperlinkButton" Height="30" HorizontalAlignment="Left" Margin="27,110,0,0" Name="hyperlinkButton1" VerticalAlignment="Top" Width="200" />
<ListBox Height="103" HorizontalAlignment="Left" Margin="37,342,0,0" Name="listBox1" VerticalAlignment="Top" Width="383" RenderTransformOrigin="0.499,1.408">
<ListBoxItem Content="ListItem1" />
<ListBoxItem Content="ListItem2" />
<ListBoxItem Content="ListItem3" />
</ListBox>
<RadioButton Content="RadioButton" Height="72" HorizontalAlignment="Left" Margin="241,73,0,0" Name="radioButton1" VerticalAlignment="Top" IsChecked="True" />
<RadioButton Content="RadioButton" Height="72" HorizontalAlignment="Left" Margin="241,126,0,0" Name="radioButton2" VerticalAlignment="Top" RenderTransformOrigin="0.528,0.056" />
<RadioButton Content="RadioButton" Height="72" HorizontalAlignment="Left" Margin="241,171,0,0" x:Name="radioButton3" VerticalAlignment="Top" RenderTransformOrigin="0.503,1.837" />
<TextBox Height="72" HorizontalAlignment="Left" Margin="37,445,0,0" Name="textBox1" Text="TextBox" VerticalAlignment="Top" Width="383" />
</Grid>
I have used calendar control and its display mode is year when my user control is loads then calender width s too large and doesn't appear when width is set .but when is select any month then width is set as it should
i m not getting what is the issue behind it
can anyone help me quickly???
Here is my code and what ever selected month will appear in textbox's text property and on click event of button my calendar control is set to visible
<StackPanel Grid.Row="0" Grid.Column="0" Orientation="HorizontalHorizontalAlignment="Left "Margin="4">
<Label Content="Month: " HorizontalAlignment="Right" VerticalAlignment="Top" FontSize="15" FontWeight="DemiBold" Margin="4"/>
<TextBox Height="23" HorizontalAlignment="Stretch" Name="SelectedMonthTextBox" VerticalAlignment="Top" Width="130" Margin="4" LostFocus="SelectedMonthTextBox_LostFocus" SelectionBrush="#FF767879"/>
<Button Content=".." Height="20" Width="20" Margin="4" Name="button" Click="button_Click" />
</StackPanel>
<Calendar Grid.Row="1" Grid.Column="0" Margin="50,-8" Panel.ZIndex="100" Name="calendar1" DisplayModeChanged="calendar1_DisplayModeChanged" DisplayDateChanged="calendar1_DisplayDateChanged" HorizontalAlignment="Left" DisplayMode="Year" Style="{StaticResource CalendarStyle}" Focusable="False" HorizontalContentAlignment="Left" VerticalAlignment="Top" />
i took a look your code and from information you provided so far, there is no any change a you describe. I believe that you should check following:
What happens in calendar1_DisplayModeChanged
How defined your style: StaticResource CalendarStyle
If it possible please post them here. I will try to help as soon as possible :)
I was trying to bind a dataContext to a grid (xaml below)
<Grid .... DataContext="{Binding Path=NewFormViewModel}" > ...</Grid>
This binding did not work and I realized the getter for NewFormViewModel was never being called.
At this point in time, The grid was the root element of the xaml file.
I then placed a canvas inside the Grid and did binding on the canvas like :
<Grid ....>
<Canvas DataContext="{Binding Path=NewFormViewModel}">
....
</Canvas>
</Grid>
The data binding worked.
Next I tried to change the grid to a canvas and do databinding agiain like this:
<Canvas.... DataContext="{Binding Path=NewFormViewModel}" > ...</Canvas>
The binding stopped working again.
In the end I settled for a Grid nested inside a canvas:
<Canvas....>
<Grid DataContext="{Binding Path=NewFormViewModel}">
....
</Grid>
</Canvas>
The question is why did the binding on the root element of the xaml not work?
or Should I have not used a Canvas/Grid as a root element at all and used something like Page/UserControl?
EDIT
My logical tree looks somthing like this:
Window <- Data binding to object o
|
*
Frame <-Data binding to obect o inherited
|
*
Canvas/Grid <- Data binding to o.NewFormViewModel failed
|
*
Canvas/Grid <- Data binding to o.NewFormViewModel Succeeds
EDIT2:
broken xaml:
<Canvas x:Class="WPFEditors.NewForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" Height="398" Width="377"
DataContext="{Binding Path=NewFormViewModel}"
>
<Grid >
<Label DataContext="Form Type" Height="31" HorizontalAlignment="Left" Margin="12,22,0,0" VerticalAlignment="Top" Width="92" />
<ComboBox Margin="148,22,6,347" ItemsSource="{Binding Path=FormTypes}" />
<Label Content="Description" Height="31" HorizontalAlignment="Left" Margin="12,58,0,0" VerticalAlignment="Top" Width="92" />
<Label Content="{Binding Path=Heading}" ToolTip="This is pulled from the Enum defined for FormTypes" Margin="148,59,6,309" />
<Label Content="Version" Height="31" HorizontalAlignment="Left" Margin="12,95,0,0" VerticalAlignment="Top" Width="92" />
<TextBox Text="Bind this later" Margin="148,97,6,270" Height="31" />
<Label Content="Approval Level" Height="31" HorizontalAlignment="Left" Margin="12,132,0,0" VerticalAlignment="Top" Width="92" />
<TextBox Height="31" Margin="148,134,6,233" Text="Bind this later" />
<Label Content="Number of Approvals" Height="31" HorizontalAlignment="Left" Margin="12,171,0,0" VerticalAlignment="Top" Width="130" />
<TextBox Height="31" Margin="148,173,6,194" Text="Bind this later" />
<Label Content="Heading" Height="31" HorizontalAlignment="Left" Margin="12,210,0,0" VerticalAlignment="Top" Width="130" />
<TextBox Height="31" Margin="148,212,6,155" Text="Bind this later" />
<Label Content="Static Data Id" Height="31" HorizontalAlignment="Left" Margin="12,247,0,0" VerticalAlignment="Top" Width="130" />
<TextBox Height="31" Margin="148,249,6,118" Text="Bind this later" />
<Label Content="{Binding Path=Errors}" Background="{Binding Path=Color}" Margin="12,325,6,6" BorderThickness="1" BorderBrush="#FF000019" />
<Button Content="Create" Margin="83,294,202,78" />
<Button Content="Create" Margin="181,294,104,78" />
<Button Content="Create" Margin="279,294,6,78" />
</Grid>
</Canvas>
In the above xaml the following line binds:
<Label Content="{Binding Path=Heading}"
even though Heading is inside a property of the viewmodel that this document inherits.
At this point I would have expected the line:
DataContext="{Binding Path=NewFormViewModel}"
to have changed the datacontext to NewFormViewModel which has no heading. All the remaining bindings fail.
If I change the beginning to :
<Canvas x:Class="NewForm"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" Height="398" Width="377"
>
<Grid DataContext="{Binding Path=NewFormViewModel}" >
The binding to Heading fails and the rest of the bindings start to work. This is the behaviour that I was expecting initially.
This xaml is nested in this file :
<Window x:Class="WPFEditors.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="{Binding Path=Heading}" Height="743" Width="1177">
<StackPanel >
<Menu IsMainMenu="True" >
<MenuItem Header="New">
<MenuItem Header="New Form" Command="{Binding Path=MenuCommand}" />
</MenuItem>
<MenuItem Header="Edit Form" ItemsSource="{Binding Path=FormsAvailable}" />
<MenuItem Header="Edit Rules" />
</Menu>
<Frame NavigationUIVisibility="Hidden" Source="{Binding Path=CurrentPage}"
LoadCompleted="Frame_LoadCompleted"
DataContextChanged="Frame_DataContextChanged"
Name="frame">
</Frame>
</StackPanel>
</Window>
and the event handlers to copy the data context to the child are :
private void Frame_LoadCompleted(object sender, NavigationEventArgs e)
{
UpdateFrameDataContext();
}
private void Frame_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
UpdateFrameDataContext();
}
private void UpdateFrameDataContext()
{
var content = frame.Content as FrameworkElement;
if (content == null)
return;
content.DataContext = frame.DataContext;
}
The Binding in the root element should work IF there is something up in the control hierarchy (like a Window or UserControl) that holds (in its DataContext) the object owning the property you're querying (NewFormViewModel).
I would like to know how to construct the ListBox in WP7 that only load 20 items at a single time, and have a footer that show "load more" if there is any.
When user press the "load more", it will load another 20 in the list without loading the previous loaded data?
I am using LINQ at the behind source.
my code for XMAL as follow:
<Grid>
<ListBox name="newsIndexListBoxEN">
<ListBoxItem>
<DataTemplate>
<StackPanel Width="410" Orientation="Horizontal" VerticalAlignment="Top" Margin="0,5,0,5">
<StackPanel Background="DarkBlue" Margin="10,0,0,0" Height="100" Width="100" VerticalAlignment="Top">
<TextBlock Name="columnsTypeTB" Text="{Binding pType}" Margin="0,0,0,0" Foreground="White" FontSize="23" HorizontalAlignment="Center" />
<Image Width="100" Height="100" VerticalAlignment="Top" HorizontalAlignment="Center" Source="Background.png" />
</StackPanel>
<StackPanel Width="300" Height="100" Margin="0,0,0,0">
<Path Margin="0,0,0,0" Data="M39,8 L389,8" Fill="DarkBlue" Height="1" Stretch="Fill" Stroke="DarkBlue" UseLayoutRounding="False" Width="400"/>
<TextBlock Margin="8,0,0,0" Text="{Binding pTitle}" Tag="{Binding pID}" Style="{StaticResource PhoneTextNormalStyle}" TextWrapping="Wrap" Width="292" Height="66" />
<TextBlock Margin="8,5,0,0" Text="{Binding pDate}" Tag="{Binding pID}" MouseEnter="NewsViewContent_mouseEnter" Style="{StaticResource PhoneTextSmallStyle}" VerticalAlignment="Bottom" TextWrapping="Wrap" Width="292" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBoxItem>
</ListBox>
</Grid>
C# Code as follow:
using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream fs = storage.OpenFile(fileName, FileMode.Open))
{
XDocument menuIndex = XDocument.Load(fs);
var menuIndexList = from query in menuIndex.Descendants("news")
orderby (int)query.Element("newsID") descending
select new mkmenu
{
pID = query.Element("newsID").Value,
pTitle = query.Element("newsTitle").Value,
pDate = query.Element("newspDate").Value,
pType = newsType
};
newsIndexListBoxEN = menuIndexList.Count();
}
}
any ideas? sample code?
You can edit your listbox template to show a "Load more" button at the end of the list. In Blend, right click on your listbox, choose Edit Template, Edit a copy. By default, your listbox has a template like this:
ScrollViewer
ItemPresenter
Wrap your ItemPresenter into a StackPanel, then add a button at the end:
ScrollViewer
StackPanel
ItemPresenter
Button
That button will always be displayed at the end of the listbox. Handle the Clicked event of that button to add items to your ObservableCollection.
You can bind your listbox to ObservableCollection and add first 20 items on your page(app) load. Than after pressing "load more" get next 20 items and add to collection. Items will automatically be added to listbox.
I have a problem with nested StackPanels. If I define StackPanels like in the code below,
button binds to command (MVVM and command pattern) but doesn't react on button click (command function is not called). When I put stackPanel4 on second position (below stackPanel3) everything works ok. When I move stackPanel4 on the last position (I have more StackPanels then two inside parent StackPanel), button is not bound and command function is not called. What could be a reason for this behavior?
If I set DataContext for stackPanel4 it works ok.
<StackPanel DataContext="{StaticResource vmUserMasterData}" Grid.Column="1" Height="320" HorizontalAlignment="Left" Margin="4,6,4,0" Name="stackPanel1" VerticalAlignment="Top" Width="491">
<StackPanel Height="40" Name="stackPanel4" Orientation="Horizontal" Width="440">
<Button Content="Update User Data" Name="button1" Height="23" Width="440" Command="{Binding Path=UpdateDataCommand}"/>
</StackPanel>
<StackPanel Height="31" Name="stackPanel3" Orientation="Horizontal" Width="440">
<sdk:Label Content="Username" Height="28" Name="label2" Width="74" />
<TextBox Height="23" Name="textBox2" Width="365" Text="{Binding Username, Mode=OneWay}" />
</StackPanel>
</StackPanel>
There must be more to this problem. We have reproduced your setup and the command event fires every time, regardless or the order of the StackPanels (basically as you would expect it to work).
Can you provide any source from your ViewModel (specifically relating to how the command is created/used)? The description of the XAML, for the case that fails, is not clear. Can you provide an exact copy of the Xaml when it fails to fire? It might be a specific combination of panels you have on your machine. One wrong closure and it would fail (e.g. if it fell outside stackPanel1 by accident).
Our reproduction (which works regardless of panel order):
Xaml:
<UserControl.Resources>
<SilverlightApplication1:ViewModel x:Key="vmUserMasterData"/>
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<StackPanel DataContext="{StaticResource vmUserMasterData}" Grid.Column="1" Height="320" HorizontalAlignment="Left" Margin="4,6,4,0" Name="stackPanel1" VerticalAlignment="Top" Width="491">
<StackPanel Height="31" Name="stackPanel3" Orientation="Horizontal" Width="440">
<sdk:Label Content="Username" Height="28" Name="label2" Width="74" />
<TextBox Height="23" Name="textBox2" Width="365" Text="{Binding Username, Mode=OneWay}" />
</StackPanel>
<StackPanel Height="40" Name="stackPanel4" Orientation="Horizontal" Width="440">
<Button Content="Update User Data" Name="button1" Height="23" Width="440" Command="{Binding Path=UpdateDataCommand}"/>
</StackPanel>
</StackPanel>
</Grid>
ViewModel code:
using System.Windows.Input;
using Microsoft.Practices.Prism.Commands;
namespace SilverlightApplication1
{
public class ViewModel
{
public ICommand UpdateDataCommand { get; set; }
public string Username { get; set; }
public ViewModel()
{
Username = "Woof!";
UpdateDataCommand = new DelegateCommand<string>(
(x) =>
{
int dog = 1; // breakpoint here
});
}
}
}