Control number of display buttons through binding - wpf

I wasn't sure the best way to word the title and couldn't find a related question, but if there is one then kindly direct me to it.
I'm trying to create a tender screen where the number of buttons displayed will be determined by how many types of tenders the user has setup (Cash, Check, Credit, Debit, Gift Card, etc).
So if I had a class like this:
public class TenderType
{
public string DisplayName { get; set; }
// ... other implementation details
}
And on my DataContext I have a TenderTypes collection declared like so:
public ObservableCollection<TenderType> TenderTypes { get; private set; }
Then how might I go about making my view udpate the number of buttons shown depending on how many TenderType instances are in the collection, and bind their Text properties to the DisplayName of the appropriate item in the collection?

You could use an ItemsControl and create a datatemplate for your TenderType to display a Button.
This way it will only show the buttons in your list
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="105" Width="156" Name="UI">
<Window.Resources>
<DataTemplate DataType="{x:Type local:TenderType}">
<Button Content="{Binding DisplayName}" />
</DataTemplate>
</Window.Resources>
<Grid DataContext="{Binding ElementName=UI}">
<ItemsControl ItemsSource="{Binding TenderTypes}"/>
</Grid>
</Window>
Code:
public partial class MainWindow : Window
{
private ObservableCollection<TenderType> _sourceData = new ObservableCollection<TenderType>();
public MainWindow()
{
InitializeComponent();
TenderTypes.Add(new TenderType { DisplayName = "Stack" });
TenderTypes.Add(new TenderType { DisplayName = "Overflow" });
}
public ObservableCollection<TenderType> TenderTypes
{
get { return _sourceData; }
set { _sourceData = value; }
}
}
public class TenderType
{
public string DisplayName { get; set; }
}
Result:

Related

How to bind the wpf datagrid scrollviewer visiblity to button visibility?

<Window x:Class="WPfDataGrid.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="525" Loaded="Window_Loaded">
<Grid>
<DataGrid x:Name="dgrdEmployee" Width="300" Height="300" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"/>
<Button Content="Navigation" x:Name="BtnNavigation" Width="90" Height="40" Margin="204,336,209,-15" />
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public class Employees
{
public string Name { get; set; }
public string Id { get; set; }
public string Address { get; set; }
}
public List<Employees> EmployeeList()
{
XDocument employees = XDocument.Load(#"C:\Employees.xml");
List<Employees> employee = (from em in employees.Descendants("Employee")
select new Employees
{
Name = em.Element("Name").Value,
Id = em.Element("Id").Value,
Address = em.Element("Address").Value
}).ToList();
return employee;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
dgrdEmployee.ItemsSource = EmployeeList();
}
}
with above code, i get the following result.
If the data grid scroll viewer is visible the button should be visible, otherwise button should be collapse. Is there any change to do so ?
I tried something like below. But it won't make sense to me.
<Button Content="Navigation" x:Name="BtnNavigation" Visibility="{Binding Visibility, ElementName=dgrdEmployee.ScrollViewer}" Width="90" Height="40" Margin="204,336,209,-15" />
The ScrollViewer is always visible. The ScrollViewer will show or hide its scrollbars depending on how much data is shown.
Assuming that you can get to the VerticalScrollBarVisiblity and HorizontalScrollBarVisiblity properties of the ScrollViewer, you could probably create a MultiBinding between those properties and the button's Visibliity property. You would probably also have to create a value converter, since the scroll bar visibility properties use a different type (that includes an Auto value in addition to the standard visibility values).

HierarchicalDataTemplate doesn’t show any children - why not?

I am trying the absolute simplest use of HierarchicalDataTemplate to bind nested data to a WPF TreeView. For some reason, the children of my tree are not visible:
Here is the entire XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<TreeView Name="ctTree">
<TreeView.Resources>
<HierarchicalDataTemplate DataType = "{x:Type src:MyClass}"
ItemsSource = "{Binding Path=Children}">
<TextBlock Text="{Binding Path=Name}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Window>
and here’s all of C# behind this, apart from usings and the namespace:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var collection = new ObservableCollection<MyClass>
{
new MyClass { Name = "parent one" },
new MyClass { Name = "parent two" },
};
collection[0].Children.Add(new MyClass { Name = "child one" });
collection[0].Children.Add(new MyClass { Name = "child two" });
ctTree.ItemsSource = collection;
}
}
class MyClass
{
public string Name { get; set; }
public ObservableCollection<MyClass> Children
= new ObservableCollection<MyClass>();
}
Note that the data template does actually apply to the items: the data is taken from the Name property, and if the template didn’t apply would show as "MyClass" instead.
How do I get the children to show? I seem to be doing exactly the same thing as all examples on HierarchicalDataTemplate.
MyClass.Children is a field, not a property. You cannot bind to a field, convert Children field to a property and everything should work then:
class MyClass
{
public string Name { get; set; }
public ObservableCollection<MyClass> Children { get; private set; }
public MyClass()
{
Children = new ObservableCollection<MyClass>();
}
}
I think Treeview.Resources is the wrong place for that. You want to put your template in Treeview.ItemTemplate.

Binding data to ComboBox WPF

I am newbie to WPF, and needs help to bind data into the ComboBox. The xaml file contains the tag below.
<UserControl x:Class="SKAT.Postfordeler.Client.UI.View.ChooseInboxView"
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"
d:DesignHeight="42" d:DesignWidth="598">
<Grid>
<StackPanel Orientation="Horizontal">
<ComboBox Name="_currentInbox" Width="180" Margin="5" Height="22" DataContext="{Binding}" />
<Label Content="Et job kører allerede i denne indbakke (1500 ud af 1700 poster behandlet)" Name="_currentProcess" Margin="5" Height="25" />
</StackPanel>
</Grid>
//Inbox class , this class was implemented in seperate project
namespace SKAT.Postfordeler.Shared.DataTypes
{
[DataContract]
public class Inbox
{
[DataMember]
public String Id { get; set; }
[DataMember]
public String Folder { get; set; }
[DataMember]
public Rule Rules { get; set; }
}
}
//This code is located in the controller, the Activate method will fire when the MainWindow was executed
public void Activate()
{
var configuration = _configurationManager.GetConfiguration();// this method gets the xaml file settings
_chooseInboxView.FillInboxes(configuration.Inboxes); // Inboxes data binds to combobox
}
and in the View code behind, I created a method to bind the data which contains a type of list
public void FillInboxes(List<Inbox> inboxes)
{
DataContext = inboxes;
}
But it won't works,Any help please?
I assume your Inbox class consists of two properties (for simplicity), but there may be any number of them:
public class Inbox
{
public int ID { get; set; }
public string Text { get; set; }
}
You write a DataTemplate, for example:
<Grid.Resources>
<DataTemplate x:Key="InboxTemplate">
<WrapPanel>
<TextBlock Text="{Binding Path=ID}"/>
<TextBlock>:</TextBlock>
<TextBlock Text="{Binding Path=Text}"/>
</WrapPanel>
</DataTemplate>
</Grid.Resources>
Then correct your ComboBox declaration like:
<ComboBox Name="_currentInbox" Width="180" Margin="5" Height="22" ItemsSource="{Binding}" ItemTemplate="{StaticResource InboxTemplate}" />
Finally you set DataContext of your ComboBox to your List<Inbox>:
public void FillInboxes(List<Inbox> inboxes)
{
_currentInbox.DataContext = inboxes;
}
EDIT: As you've asked for a simpler solution, you can just override ToString() method of your Inbox class:
protected override string ToString()
{
return ID.ToString() + ":" + Text;
}
Instead of DataContext={Binding} you should have ItemsSource={Binding}.
The data context for any frameworkelement in the visual tree is by default {Binding}.
<ComboBox Name="_currentInbox"
SelectedItem="Hoved"
Width="180"
Margin="5"
Height="22"
DisplayMemberPath="Name"
ItemSource="{Binding}" />
Also for the combobox to display text of the items correctly I suppose you need DisplayMemberPath too. I assumed the property from Inbox class that you need to display is Name. Please replace with your relevant property name.
If your Inbox class is like,
public class Inbox
{
public int ID { get; set; }
public string Text { get; set; }
}
And if you do not want to change your xmal, the code behind method should be like this,
public void FillInboxes(List<Inbox> inboxes)
{
_currentInbox.DisplayMemberPath = "Text"; // To display the 'Text' property in the combobox dropdown
//_currentInbox.DisplayMemberPath = "ID"; // To display the 'ID' property in the combobox dropdown
_currentInbox.DataContext = inboxes;
}

Missing Edit Option on Silverlight 4 DataForm

I’m trying out the Silverlight 4 beta DataForm control. I don’t seem to be able to get the edit and paging options at the top of the control like I’ve seen in Silverlight 3 examples. Has something changed or am I doing something wrong? Here’s my code:
<UserControl x:Class="SilverlightApplication7.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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" xmlns:dataFormToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.DataForm.Toolkit">
<Grid x:Name="LayoutRoot" Background="White">
<dataFormToolkit:DataForm HorizontalAlignment="Left" Margin="10" Name="myDataForm" VerticalAlignment="Top" />
</Grid>
</UserControl>
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
Movie movie = new Movie();
myDataForm.CurrentItem = movie;
}
public enum Genres
{
Comedy,
Fantasy,
Drama,
Thriller
}
public class Movie
{
public int MovieID { get; set; }
public string Name { get; set; }
public int Year { get; set; }
public DateTime AddedOn { get; set; }
public string Producer { get; set; }
public Genres Genre { get; set; }
}
}
The behaviour of your code above is identical in VS2008+SL3.
The DataForm only provides the navigation bar if you provide it with a set of items assigned to the ItemsSource property. By assigning directly to the CurrentItem property you are in effect asking the DataForm "please edit this item", which is exactly what its doing.
AnthonyWJones is correct on the paging question. You need to bind to the collection to get the Next/Previous options. I believe you need to implement IEditableObject for the View/Edit option to appear.

Silverlight Control Toolkit TreeView not rendering items

I'm trying to build a SL app with a TreeView in it. Here's my XAML:
<UserControl xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit"
xmlns:tkwin="clr-namespace:System.Windows;assembly=System.Windows.Controls.Toolkit"
xmlns:basics="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SL.MyApp.Page"
Width="800" Height="600">
<controls:DockPanel>
<controls:TreeView Name="siteTree" controls:DockPanel.Dock="Left" Width="150">
<controls:TreeView.ItemTemplate>
<tkwin:HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</tkwin:HierarchicalDataTemplate>
</controls:TreeView.ItemTemplate>
</controls:TreeView>
<basics:TabControl controls:DockPanel.Dock="Right" TabStripPlacement="Top">
<basics:TabItem Header="Sites"></basics:TabItem>
<basics:TabItem Header="Lists"></basics:TabItem>
<basics:TabItem Header="Users"></basics:TabItem>
</basics:TabControl>
</controls:DockPanel>
</UserControl>
And the relevant codebehind:
namespace SL.MyApp
{
public partial class Page : UserControl
{
private ObservableCollection<WebDescriptor> _webHierarchy = new ObservableCollection<WebDescriptor>();
public Page(WebsSvc.WebsSoapClient websClient)
{
InitializeComponent();
siteTree.ItemsSource = _webHierarchy;
websClient.GetWebCollectionCompleted
+= new EventHandler<SL.SiteBuilder.WebsSvc.GetWebCollectionCompletedEventArgs>(websClient_GetWebCollectionCompleted);
websClient.GetWebCollectionAsync();
// TODO: some kind of spinner or progress bar needs to be started.
}
void websClient_GetWebCollectionCompleted(object sender, SL.SiteBuilder.WebsSvc.GetWebCollectionCompletedEventArgs e)
{
foreach (XElement xe in e.Result.Elements())
{
_webHierarchy.Add(ServiceObjectParser<WebDescriptor>.Parse(xe));
}
}
}
}
Update: The WebDescriptor class:
public class WebDescriptor
{
public string Title { get; set; }
public string Url { get; set; }
public List<WebDescriptor> Children { get; set; }
}
My problem is that nothing renders in the TreeView at all. I have verified that the results obtained in websClient_GetWebCollectionCompleted are valid and correct, but....nothing.
Any ideas?
in websClient_GetWebCollectionCompleted:
siteTree.ItemsSource = _webHierarchy;
Also, change your binding on the TextBlock in the Treeview to be {Binding Title}
After looking at the binding trace output, I finally realized I was trying to bind to a field instead of a property.
Doh!

Resources