I'm having problems to do a binding in Windows Phone. Hope you can help me.
I have the following Data Template:
<DataTemplate>
<TextBox Name="txt1"/>
<TextBox Name="txt2"/>
</DataTemplate>
I have a ListBox that receives the following Class in the ItemsSource Property:
public class Product
{
private int _id;
public int Id
{
get { return _id; }
set { _id = value; }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
Is there anyway to bind the Text property with the Object of the ListBoxItem like...
<TextBox Name="txt1" Text={Binding ElementName=ListBox, Path=SelectedItem.Product.Name}/>
I got a working example
xaml:
Here's the code
<Grid x:Name="gdTest" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5,0,5,0" >
<ListBox Width="400" Margin="10" x:Name="lstDemo">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Id}" Margin="20" />
<TextBlock Text="{Binding Path=Name}" Margin="20"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using StackOverFlowTestApp.Resources;
using Microsoft.Phone.Tasks;
using Microsoft.Phone.UserData;
using Windows.UI;
using System.Windows.Media;
using System.IO;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework;
namespace StackOverFlowTestApp
{
public partial class MainPage : PhoneApplicationPage
{
private SoundEffect effect;
// Constructor
public MainPage()
{
InitializeComponent();
List<Product> liProd = new List<Product>();
for (int i = 0; i < 10; i++) {
liProd.Add(new Product()
{
Id = i,
Name = "Anobik" + i.ToString()
});
}
lstDemo.ItemsSource = liProd;
}
}
public class Product
{
private int _id;
public int Id
{
get { return _id; }
set { _id = value; }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
}
}
if you require any more explanation then let me know.
Related
I hope I can explain my problem properly.
I have a datagrid bound to an ObservableCollection object, and a TextBox bound to the selected item of my datagrid.
When I programmatically modify the SelectedItem property value (Name), my TextBox text value is not updated !
here is my design code:
<DataGrid Name="grid" HorizontalAlignment="Left" Margin="119,28,0,0" VerticalAlignment="Top" Height="237" Width="200" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="nom" Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataGrid.Columns>
</DataGrid>
<TextBox Name="textbox" Text="{Binding ElementName=grid, Path=SelectedItem.Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Height="18" Margin="119,276,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="200"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="392,54,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
and here is my Code Behind:
ObservableCollection<Element> obs;
class Element
{
public string Name { get; set; }
public Element(string name) { Name = name; }
}
public MainWindow()
{
InitializeComponent();
obs = new ObservableCollection<Element>() { new Element("element2"), new Element("element2"), new Element("element3")};
grid.ItemsSource = obs;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var sel = grid.SelectedItem as Element;
sel.Name = "something";
grid.Items.Refresh(); //this updates the selected element to "something" but does nothing to the textbox
}
Problem solved.
I had to fire PropertyChanged event whenever a modification is made to the model.
here my new code:
class Element : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
}
}
public Element(string name) { Name = name; }
}
I want to use twoway binding in my customcontrol. It's codes;
CustomControl;
<Grid>
<PasswordBox x:Name="passwordB" GotFocus="PasswordBox_GotFocus" LostFocus="PasswordBox_LostFocus" PasswordChanged="passwordB_PasswordChanged" Style="{StaticResource AkbankControlStyleWatermarkPasswordBoxLoginFormInputPasswordBox}"></PasswordBox>
<TextBlock x:Name="lblWaterMark" MouseLeftButtonDown="lblWaterMark_Tapped" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="20,10,20,10" Opacity="0.8" FontFamily="Segoe UI" FontSize="16" Foreground="#FF8E8E8E" FontWeight="SemiBold"></TextBlock>
</Grid>
It's name is WatermarkPasswordTextBox :)
DependencyProperty;
public static readonly DependencyProperty PasswordProperty =
DependencyProperty.Register(
"PassText",
typeof(string),
typeof(WatermarkPasswordTextBox),
new PropertyMetadata(""));
Properties;
private string _passText = "";
public string PassText
{
get
{
if (passwordB != null)
{
_passText = passwordB.Password;
return _passText;
}
else
{
return String.Empty;
}
}
set
{
if (passwordB != null)
{
SetProperty<string>(ref _passText, value, "PassText");
passwordB.Password = _passText;
passwordB_PasswordChanged(passwordB, null);
}
else
{
SetProperty<string>(ref _passText, value, "PassText");
}
}
}
OnApplyTemplate ;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.SetBinding(
WatermarkPasswordTextBox.PasswordProperty,
new Binding
{
Path = new PropertyPath("PassText"),
Mode = BindingMode.TwoWay,
Source = this
});
}
My Xaml;
<CustomControls:WatermarkPasswordTextBox
PassText="{Binding Password,Mode=TwoWay}"
Padding="5"
x:Name="CustomerPasswordTextBox"
x:FieldModifier="public"
LenghtMax="6"
Watermark="{Binding LocalizedResources.PasswordWatermarkWatermark,Source={StaticResource LocalizedStrings}}"
RelayedKeyUp="CustomerPasswordTextBox_KeyUp"
HorizontalContentAlignment="Left"/>
Error Code;
System.ArgumentException: Object of type 'System.Windows.Data.Binding' cannot be converted to type 'System.String'.
This code is giving runtime error.
Thanks.
I am building a Windows Phone App, and I am trying to bind the ObservableCollection with nested struct without success.
MyViewModel.cs
public class MyViewModel : PropertyChangedBase
{
private Player _Player1;
public Player Player1
{
get { return _Player1; }
set
{
if (!value.Equals(_Player1))
{
_Player1 = value;
NotifyOfPropertyChange(() => Player1);
}
}
}
private Player _Player2;
public Player Player2
{
get { return _Player2; }
set
{
if (!value.Equals(_Player2))
{
_Player2 = value;
NotifyOfPropertyChange(() => Player2);
}
}
}
public struct Player
{
public string Name;
public bool IsWinner;
}
}
MyPageViewModel.cs
public class MyPageViewModel : Screen
{
public ObservableCollection<MyViewModel> Matches { get; private set; }
public MyPageViewModel()
{
this.Matches = new ObservableCollection<MyViewModel>();
LoadData();
}
public void LoadData()
{
// Matches
this.Matches.Add(new MyViewModel()
{
Player1 = new MyViewModel.Player
{ Name = "Jhonn", IsWinner = false },
Player2 = new MyViewModel.Player
{ Name = "Marrie", IsWinner = true }
});
}
}
MyPage.xaml
<ListBox Margin="0,0,-12,0" ItemsSource="{Binding Matches}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17" Width="432">
<TextBlock Text="{Binding Player1.Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding Player2.Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I have no binding error, but no players names are showed. I always have a blank screen.
Your problem is here:
public struct Player
{
public string Name;
public bool IsWinner;
}
In order to be bound, Name needs to be a property. Make Player a class and expose Name as a property on the class and you'll be golden:
public class Player
{
public string Name {get; set;}
public bool IsWinner {get;set;}
}
You should be able to get away without implementing INotifyPropertyChanged, as long as you only set them one time. If they're going to change, go ahead and implement INPC.
I need to build a form where I have 2 comboBoxes .
Select country and you get the cities of that country.
I m new to wpf so help me as I not sure what I am missing.
At the moment It doesnt even populate it.
Any help suggestions really appreaciated!
This is what I have done:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var window = new MainWindow();
var countryCitymodel = new CountryCityModel();
var repository = new CountryCityRepository();
var viewModel = new CountryCityViewModel(countryCitymodel, repository);
window.Show();
}
}
MainWindow xaml
<Window x:Class="WpfDatabinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:view="clr-namespace:WpfDatabinding.Views"
Title="MainWindow" Height="350" Width="525">
<Grid>
<view:CountryCityView />
</Grid>
</Window>
CountryCityView xaml
<UserControl x:Class="WpfDatabinding.Views.CountryCityView"
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="75" d:DesignWidth="300">
<Grid Height="64" Width="291">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="97"/>
<ColumnDefinition Width="13" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Countries" Margin="-6,6,5,0" Grid.ColumnSpan="2" Height="33"></Label>
<Label Grid.Row="1" Content="Cities" Grid.ColumnSpan="2"></Label>
<ComboBox Name="cboCountries"
ItemsSource="{Binding Path=Countries}"
SelectedValuePath="Name"
DisplayMemberPath="{Binding Name}"
Grid.Column="2"
Margin="0,10"></ComboBox>
<ComboBox Name="cboCities"
Grid.Column="2"
Grid.Row="1"
ItemsSource="{Binding Path=Cities}" Height="20" Margin="0,0,0,1">
</ComboBox>
</Grid>
</UserControl>
CountryCityView
public partial class CountyrCityView:UserControl
{
public CountryCityView()
{
InitializeComponents();
}
public CountryCityView(CountryCityViewModel countryCityViewModel)
{
InitializeComponents();
DataContext=countryCityViewModel;
}
}
CountryCityViewModel
public class CountryCityViewModel : ViewModelBase
{
private readonly CountryCityModel _countryCityModel;
readonly CountryCityRepository _repository;
RelayCommand _getCountriesCommand;
private RelayCommand _getCitiesCommand;
public CountryCityViewModel(CountryCityModel countryCityModel, CountryCityRepository repository)
{
_countryCityModel = countryCityModel;
_repository = repository;
GetCountries.Execute(null);
}
public List<Country> Countries
{
get { return _countryCityModel.Countries; }
set
{
_countryCityModel.Countries = value;
OnPropertyChanged("Countries");
}
}
public List<City> Cities
{
get { return _countryCityModel.Cities; }
set
{
_countryCityModel.Cities = value;
OnPropertyChanged("Cities");
}
}
public Country SelectedCountry
{
get { return _countryCityModel.SelectedCountry; }
set
{
_countryCityModel.SelectedCountry = value;
OnPropertyChanged("SelectedCountry");
}
}
public City SelectedCity
{
get { return _countryCityModel.SelectedCity; }
set
{
_countryCityModel.SelectedCity = value;
OnPropertyChanged("SelectedCity");
}
}
public ICommand GetCountries
{
get
{
if (_getCountriesCommand == null)
{
_getCountriesCommand = new RelayCommand(param => GetCountryList(), param => CanGetCountries());
}
return _getCountriesCommand;
}
}
public ICommand GetCities
{
get
{
if (_getCitiesCommand == null)
{
_getCitiesCommand = new RelayCommand(param => GetCityList(), param => CanGetCities());
}
return _getCitiesCommand;
}
}
private List<Country> GetCountryList()
{
Countries = _repository.GetCountries();
return Countries;
}
private static bool CanGetCountries()
{
return true;
}
private List<City> GetCityList()
{
Cities = _repository.GetCities(SelectedCountry.Name);
return Cities;
}
private static bool CanGetCities()
{
return true;
}
}
Model
public class CountryCityModel
{
public List<Country> Countries { get; set; }
public List<City> Cities { get; set; }
public Country SelectedCountry{ get; set; }
public City SelectedCity { get; set; }
}
Types
public class City
{
public string Name { get; set; }
public string CountryName { get; set; }
}
public class Country
{
public string Name { get; set; }
}
Repository
public List<Country>GetCountries()
{
return new List<Country>
{
new Country{Name = "Italy"},
new Country{Name = "Germany"},
new Country{Name = "France"},
new Country{Name = "England"}
};
}
public List<City> GetCities(string countryName)
{
return Cities().Where(c => c.CountryName == countryName).ToList();
}
private static IEnumerable<City> Cities()
{
return new List<City>
{
new City { CountryName="Italy",Name = "Rome"},
new City {CountryName="France",Name = "Paris"},
new City{CountryName="Germany",Name ="Berlin"},
new City{CountryName="England",Name ="London"}
};
}
}
Are you setting the data context of the view to your ViewModel somewhere? I don't see that in the code listed above.
e.g.
var viewModel = new CountryCityViewModel(countryCitymodel, repository);
window.DataContext = viewModel;
New to wpf and through a learning curve.
I have a userControl with a Toolbar Save Button and a TextBox.
What I am trying to achieve is as follows
When I press the save Button in the toolbar I should record in the textbox that I am about to save and that I have saved the customer (CustomerView UserControl)
I seem to have 2 problems
1) that the SaveCommand is not hooked I thought I had hooked it
2) is not writing the action to the textbox.
Could you tell me where I am going wrong?
Thanks a lot!!!
MainWindow.xaml
<Window x:Class="MyCompany.CustomerStore.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:view="clr-namespace:MyCompany.CustomerStore.Views"
Title="MainWindow" Height="350" Width="525">
<Grid>
<view:CustomerView></view:CustomerView>
</Grid>
CustomerView.xaml
<UserControl x:Class="MyCompany.CustomerStore.Views.CustomerView"
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">
<Grid>
<DockPanel LastChildFill="True">
<ToolBar DockPanel.Dock="Top">
<Button Command="{Binding Path=SaveCommand}">Save</Button>
</ToolBar>
<TextBox Name="txtPrintAction" Text="{Binding CustomerLog, Mode=TwoWay}"></TextBox>
</DockPanel>
</Grid>
CustomerModel.cs
public class CustomerModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string CustomerLog { get; set; }
}
CustomerViewModel.cs
public class CustomerViewModel:WorkspaceViewModel,ICustomerViewModel
{
readonly CustomerModel _customerModel;
RelayCommand _saveCommand;
public CustomerViewModel(CustomerModel customer)
{
_customerModel = customer;
}
public string FirstName
{
get { return _customerModel.FirstName; }
set
{
_customerModel.FirstName = value;
base.OnPropertyChanged("FirstName");
}
}
public string LastName
{
get { return _customerModel.LastName; }
set
{
_customerModel.LastName = value;
base.OnPropertyChanged("LastName");
}
}
public string CustomerLog
{
get { return _customerModel.CustomerLog; }
set
{
_customerModel.CustomerLog = value;
base.OnPropertyChanged("CustomerLog");
}
}
public ICommand SaveCommand
{
get
{
if (_saveCommand == null)
{
_saveCommand = new RelayCommand(param => Save(), param => CanSave);
}
return _saveCommand;
}
}
private void Save()
{
AppendToLog("I am about to save");
//Pretend we have saved the customer
AppendToLog("CustomerSaved");
}
internal void AppendToLog(string text)
{
_customerModel.CustomerLog += text + Environment.NewLine; ;
OnPropertyChanged("CustomerLog");
}
static bool CanSave
{
get
{
return true;
}
}
Where do you declare a relationship between the view
x:Class="MyCompany.CustomerStore.Views.CustomerView
and the model class CustomerViewModel?
I don't see that anywhere.
I think you need to set the DataContext of the View to the Model.