WPF Custom Control Not Displaying Data - c#

Here I have my custom control:
xaml:
<UserControl x:Class="Tasks.Assets.Objects.Card"
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"
xmlns:local="clr-namespace:Tasks.Assets.Objects"
mc:Ignorable="d"
d:DesignHeight="200" d:DesignWidth="150">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="135"/>
<RowDefinition Height="5"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Rectangle Fill="{DynamicResource MutedWhite}" Grid.RowSpan="4" Grid.ColumnSpan="2"/>
<TextBlock x:Name="textBlock" Grid.Column="1" Text="{Binding Path=Title}" TextWrapping="Wrap" FontFamily="/Tasks;component/Assets/Fonts/#Abel" FontSize="24"/>
<Rectangle Fill="{DynamicResource MutedGrey}" Grid.Row="1" Grid.ColumnSpan="2"/>
</Grid>
C# Code Behind:
public partial class Card : UserControl
{
public Card()
{
InitializeComponent();
}
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(Card), new UIPropertyMetadata(""));
}
and on MainWindow.xaml
<Objects:Card Grid.Column="1" Grid.Row="1" Title="Say Something Here"/>
The rectangles are rendering but my text is not rendering in the control
I have tested this by adding text without the binding which works fine. However the problem is at the binding. I want to have the ability to set the text object on main window through the use of a xaml tag but I cannot do this as it will not show me. Any help appreciated :)

The Text binding in the UserControl's XAML is missing a source object, which should be the UserControl instance.
One way to set the binding source to the UserControl instance is to set the RelativeSource property:
<TextBlock Text="{Binding Path=Title,
RelativeSource={RelativeSource AncestorType=UserControl}}" ... />
You may also set the x:Name attribute on the UserControl, and set the binding's ElementName:
<UserControl ... x:Name="self">
...
<TextBlock Text="{Binding Path=Title, ElementName=self}" ... />
...
</UserControl>

Related

Accessing/Setting Custom Text Properties of codebehind through XAML

Having some trouble getting my head around all the DP's i've recreated a very simple version of of my problem to try and sort out what the issue is. Alas, im still stumped..
I Have a custom userControl, and am attempting to set the properties of a textblock through the page that is instantiating that control. At the moment, in this version below, as a means of teaching myself im only trying to access a property from code behind.
The reason I wish to set custom text properties etc. is because I wish to have multiple versions of the control on the page with custom behaviour/text etc.
Here is my code behind.
public partial class FeedbackCtrl : UserControl
{
public bool IsFlagSet
{
get { return (bool)GetValue(IsFlagSetProperty); }
set { SetValue(IsFlagSetProperty, value); }
}
public static readonly DependencyProperty IsFlagSetProperty =
DependencyProperty.Register("IsFlagSet", typeof(bool), typeof(FeedbackCtrl), new PropertyMetadata(false));
public FeedbackCtrl()
{
InitializeComponent();
this.DataContext = this;
}
}
And my XAML..
<UserControl x:Class="Pipeline_General.Custom_Controls.FeedbackCtrl" x:Name="ThisCtrl"
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"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Expander HorizontalAlignment="Stretch" >
<Expander.Header Name="Header">
<Grid HorizontalAlignment="Stretch" Width="NaN">
<Border Background="Transparent" HorizontalAlignment="Stretch" BorderBrush="gray" BorderThickness="0,0,0,1"
Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Expander}}, Path=ActualWidth}">
<TextBlock Foreground="#FFFF72D2" Text="{Binding Path=IsFlagSet}">
</TextBlock>
</Border>
</Grid>
</Expander.Header>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="1">
<StackPanel Orientation="Vertical" VerticalAlignment="Top" Margin="5"/>
</ScrollViewer>
</Grid>
</Expander>
</Grid>

Binding Two ComboBoxs to the Same Source WPF

I have the following XAML where I have two combobox controls with the same ItemsScource. I used the IsSynchronizedWithCurrentItem=False to attempt to get them to act individually. But still changing one changes the other.
XAML
<Page x:Class="HaMmeR.FantasyFootball.TradeEvalPage"
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="300" d:DesignWidth="300"
Title="TradeEvalPage">
<Grid x:Name="masterPanel">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" Grid.Column="0" Style="{DynamicResource dockLsLabel}">
<Label x:Name="teamName1Lbl" Content="Team Name" Style="{DynamicResource lsLabel}" />
<!--IsSynchronizedWithCurrentItem=False Treat datasource as individual-->
<ComboBox x:Name="teamName1Cmb" Margin="2" DockPanel.Dock="Right"
ItemsSource="{Binding Path=FantasyTeams}"
IsSynchronizedWithCurrentItem="False"
DisplayMemberPath="TeamName"
SelectionChanged="teamName1Cmb_SelectionChanged"
SelectedValuePath="TeamName" SelectedValue="{Binding Path=TeamName}"/>
</DockPanel>
<DockPanel Grid.Row="0" Grid.Column="1" Style="{DynamicResource dockLsLabel}">
<Label x:Name="teamName2Lbl" Content="Team Name" Style="{DynamicResource lsLabel}" />
<ComboBox x:Name="teamName2Cmb" Margin="2" DockPanel.Dock="Right"
ItemsSource="{Binding Path=FantasyTeams}"
IsSynchronizedWithCurrentItem="False"
DisplayMemberPath="TeamName"
SelectionChanged="teamName2Cmb_SelectionChanged"
SelectedValuePath="TeamName" SelectedValue="{Binding Path=TeamName}"/>
</DockPanel>
</Grid>
</Page>
.cs File
public partial class TradeEvalPage : Page
{
private FantasyLeague league;
public TradeEvalPage(FantasyLeague League)
{
InitializeComponent();
league = League;
//FantasyTeamCollection team1Source = new FantasyTeamCollection(league.FantasyTeams.ToList<FantasyTeam>());
//FantasyTeamCollection team2Source = new FantasyTeamCollection(league.FantasyTeams.ToList<FantasyTeam>());
//teamName1Cmb.DataContext = team1Source;
//teamName2Cmb.DataContext = team2Source;
masterPanel.DataContext = league;
//mainContent.Text = string.Format("You clicked Trade Evalution of {0}", league.LeagueName);
}
}
I can't figure out what I'm doing wrong. Any help would be appreciated.
I think because you Bind the selectedValue to the TeamName.
SelectedValue="{Binding Path=TeamName}"
If you remove the bind, they probably work. I think whats happen here is, when you change the selection in one combobox, the value of the new selected item is written in the current items-name. So it looks that the first combobox does the same, but if you open it, you'll see that value twice.

ListView showing empty TextBlocks at runtime

I'm experiencing a strange problem with data-binding. In the designer everything is shown correctly, but at runtime my ListView just contains those TextBlocks with an empty string in them. I'm using MVVM light for ViewModels. Most of the code was generated by VS2012 by creating a split page for WindowsStore-Apps.
Here's my XAML: ( I already removed some other parts, like the VisualStateManager, but without effect so that doesn't seem to be an issue.)
<common:LayoutAwarePage
x:Name="pageRoot"
x:Class="Kunden.OrderPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Kunden"
xmlns:common="using:Kunden.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding SelectCustomersViewModel, Source={StaticResource Locator}}">
<Page.Resources>
<CollectionViewSource
x:Name="itemsViewSource"
Source="{Binding Items}"/>
</Page.Resources>
<Grid Style="{StaticResource LayoutRootStyle}">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="primaryColumn" Width="610"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid x:Name="titlePanel">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button
x:Name="backButton"
Click="GoBack"
IsEnabled="{Binding DefaultViewModel.CanGoBack, ElementName=pageRoot}"
Style="{StaticResource BackButtonStyle}"/>
<TextBlock x:Name="pageTitle" Grid.Column="1" Text="Werbeauswahl" Style="{StaticResource PageHeaderTextStyle}" Margin="0,0,-2,40"/>
</Grid>
<!-- Elementliste mit vertikalem Bildlauf -->
<ListView
x:Name="itemListView"
AutomationProperties.AutomationId="ItemsListView"
AutomationProperties.Name="Items"
TabIndex="1"
Grid.Row="1"
Margin="-10,-10,0,0"
Padding="120,0,0,60"
IsSwipeEnabled="False"
SelectionChanged="ItemListView_SelectionChanged"
ItemsSource="{Binding AvaiableCountries}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
... closing brackets etc.
The IEnumerableI want to bind:
private IEnumerable<Country> avaiableCountries;
public IEnumerable<Country> AvaiableCountries
{
get { return avaiableCountries; }
set { avaiableCountries = value; RaisePropertyChanged(() => AvaiableCountries); }
}
The data value object CountryI need for my LINQ-Query:
public class Country
{
internal string Name { get; set; }
}
Please try try changing the access modifier of the Name property from internal to public and see whether that fixes your problem?
If that doesn't work post the code where you're populating AvaiableCountries with data

Error template not working when a ControlTemplate is applied to the window

I have a simple application with App.xaml, MainWindow.xaml and a Person class. When I don't specify the template, my ValidateOnDataErrors works perfectly, putting a red border around my textbox when it is in error. However, as soon as I insert the ' Template="{StaticResource WindowTemplate}" ' in the Window tag of my MainWindow.xaml, the field is still validated but the red border disappears.
App.xaml :
<Application x:Class="WpfPOC.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ControlTemplate TargetType="Window" x:Key="WindowTemplate">
<Grid Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Control x:Name="FocusCatcher"></Control>
<TextBlock>Menu Section</TextBlock>
<ContentPresenter Grid.Row="1" />
<StatusBar Height="23" VerticalAlignment="Bottom" Grid.Row="2">
<TextBlock Text="Current Editing Mode" />
</StatusBar>
</Grid>
</ControlTemplate>
</Application.Resources>
</Application>
MainWindow.xaml :
<Window x:Class="WpfPOC.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:data="clr-namespace:WpfPOC"
Template="{StaticResource WindowTemplate}"
Title="MainWindow"
Height="350"
Width="525">
<Window.Resources>
<data:Person x:Key="myDataSource" Name="Joe"/>
</Window.Resources>
<Grid>
<TextBox Height="23" Width="120" Text="{Binding Source={StaticResource myDataSource}, Path=Name, ValidatesOnDataErrors=True}" />
</Grid>
</Window>
Person.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
namespace WpfPOC
{
public class Person : IDataErrorInfo
{
public string Name { get; set; }
#region IDataErrorInfo Members
public string Error
{
get { return string.Empty; }
}
public string this[string columnName]
{
get { return "Simulated error"; }
}
#endregion
}
}
Thank you in advance for your help.
This happens because the default ControlTemplate used for displaying validation errors (draws a red border around the control) uses the AdornerLayer.
You have created a new ControlTemplate for the entire Window and left out the AdornerDecorator (which the default ControlTemplate for Window supplies)
So just wrap your new ControlTemplate with a AdornerDecorator like so:
<ControlTemplate TargetType="Window" x:Key="WindowTemplate">
<AdornerDecorator>
<Grid Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Control x:Name="FocusCatcher"></Control>
<TextBlock>Menu Section</TextBlock>
<ContentPresenter Grid.Row="1" />
<StatusBar Height="23" VerticalAlignment="Bottom" Grid.Row="2">
<TextBlock Text="Current Editing Mode" />
</StatusBar>
</Grid>
</AdornerDecorator>
</ControlTemplate>

How to place an XAML usercontrol in a grid

I have the following main.xaml and usercontrol.
I need to place several times the user control on the 2nd row, 2nd column of the grid, By using visual studio it wont allow to drag and drop the user control, so I suppose I have to do it by code, I just dont know how
MainPage.xaml
<Grid HorizontalAlignment="Left" Height="768" VerticalAlignment="Top" Width="1366" x:Name="grid" Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="150"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Border BorderBrush="White" BorderThickness="3" Grid.Column="1" Background="Red" CornerRadius="30"/>
<TextBlock x:Name="txtCountry" Grid.Column="1" TextWrapping="Wrap" FontSize="36" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock x:Name="txtTime" Grid.Row="1" TextWrapping="Wrap" FontSize="180" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
Usercontrol
<UserControl
x:Class="AlarmPro.TimeOnCity"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AlarmPro"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="150"
d:DesignWidth="250">
<Grid Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border BorderBrush="#FFDE6A6A" BorderThickness="1" Grid.Row="0" Grid.Column="0" Background="#FFDC4646">
<TextBlock TextWrapping="Wrap" Text="TextBlock" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
</Border>
<Border BorderBrush="Black" BorderThickness="1" Grid.Row="1" Background="#FFAE4F00">
<TextBlock TextWrapping="Wrap" Text="TextBlock" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="36"/>
</Border>
</Grid>
</UserControl>
Do you mean like this?
<my:UserControlName Grid.Column="2" Grid.Row="2" ... />
<my: in this case is the alias for the CLR namespace the UserControl resides in. It is defined at the top of your XAML, inside the <Window> or <UserControl> tag depending on context.
For example,
<Window ...
xmlns:my="clr-namespace:AssemblyName"
...
/>
MainPage.Xaml
<Page
x:Class="UserControlExample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UserControlExample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="MainContent" Background="Azure" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden">
<local:UserControl1 x:Name="MyHelloWorldUserControl" Grid.Row="1" />
</ScrollViewer>
</Grid>
</Page>
UserControl1.xaml
<UserControl
x:Class="UserControlExample.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UserControlExample"
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">
<Grid Background="Bisque">
<StackPanel>
<StackPanel Orientation="Horizontal" Height="81">
<TextBlock Text="Your Name is" Foreground="Blue" FontSize="30" Margin="0,0,0,10"/>
<TextBox x:Name="Input" Background="White" Width="225" />
</StackPanel>
<Button Content="Click Me" Foreground="Brown" FontSize="30" Click="Button_Click"/>
<TextBlock x:Name="Output" FontSize="100"/>
</StackPanel>
</Grid>
</UserControl>
MainPage.xaml, I am binding a login UserControl
by using the namespace : xmlns:UC="clr-namespace:Test.Views" , since I have my usercontrol in Folder named "Views".
<ScrollViewer>
<UC:Login BtnLoginClick="Login_BtnLoginClick"/>
</ScrollViewer>
Login.cs
public partial class Login : UserControl {
public event EventHandler BtnLoginClick;
public Login()
{
InitializeComponent();
}
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
string userName = txtUserName.Text;
string userPassword = txtUserPassword.Password.Trim();
if (userName != null && userName != string.Empty && userPassword != null && userPassword != string.Empty)
{
if (this.BtnLoginClick != null)
{
this.BtnLoginClick(this, e);
}
}
else
{
MessageBox.Show("Invalid username or password");
}
}
}
Finally, dont forgot to use the event handler in MainPage.xaml to capture the button clicked event from Login Usercontrol to do other actions.
MainPage.xaml
<UC:Login BtnLoginClick="Login_BtnLoginClick"/>
Here "BtnLoginClick" its an event Handler defined in the Login.xaml[User Control].
Create new event for this "BtnLoginClick" event as i created "Login_BtnLoginClick".
MainPage.cs
private void Login_BtnLoginClick(object sender, EventArgs e)
{
Messagebox.Show("Event captured successfully");
////Here you can add your stuffs...
}
For UWP, in UserControl.xaml, find the local namespace xmlns:local notation: xmlns:local="using:ProjectName.Folder" at the top (by convention, C# namespaces are named the same way as the folder that contains them, so folder also means namespace).
In MainPage.xaml, add a reference to this namespace. The reference prefix can be any name desired: for example, CustomPrefix, as in xmlns:CustomPrefix="using:ProjectName.Folder". Then, anywhere in MainPage.xaml, display the control by prefixing its name with <CustomPrefix:...>.
UserControl.xaml
<UserControl
xmlns:local="using:ProjectName.Folder">
MainPage.xaml
<Page
xmlns:CustomPrefix="using:ProjectName.Folder">
<CustomPrefix:UserControl />
</Page>
The project needs to be built to discard XAML errors in Visual Studio, otherwise the design view remains blank and the XAML has green squiggles.

Categories

Resources