the TextBlock binding does not work and I cant figure why...
(This Code Works but the TextBlock does not get Updated )
XAML
<TextBlock x:Name="filterAllText"
Text="{Binding UpdateSourceTrigger=PropertyChanged}" />
Codebehind
filterAllText.DataContext = LogSession.test.MyCoynt;
C#
public class Test : INotifyPropertyChanged {
public int myCoynt;
public int MyCoynt {
get { return myCoynt; }
set {
myCoynt = value;
NotifyPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged(
[CallerMemberName] String propertyName = "") {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Try this:
<TextBlock x:Name="filterAllText"
Text="{Binding UpdateSourceTrigger=PropertyChanged, Path=MyCoynt}" />
And set your DataContext like:
filterAllText.DataContext = LogSession.test;
<TextBlock x:Name="filterAllText" Text="{Binding Path=., UpdateSourceTrigger=PropertyChanged}" />
this should work but its not the usual way
EDIT: the better way is the anwser from Goanne
Related
I have a wpf app I'm using some xaml code that should let me view pdf files, I just started to use data biding and don't figure way this not works for me.
here m XAML:
<Grid>
<telerik:RadPdfViewerToolBar RadPdfViewer="{Binding ElementName=pdfViewer, Mode=OneTime}" SignaturePanel="{Binding ElementName=signaturePanel, Mode=OneTime}"/>
<telerik:SignaturePanel x:Name="signaturePanel" PdfViewer="{Binding ElementName=pdfViewer, Mode=OneWay}" Grid.Row="1"/>
<telerik:RadPdfViewer x:Name="pdfViewer" DocumentSource="{Binding Path=PathOfPdf, Mode=TwoWay}" DataContext="{Binding CommandDescriptors, ElementName=pdfViewer}" telerik:RadPdfViewerAttachedComponents.RegisterSignSignatureDialog="True" telerik:RadPdfViewerAttachedComponents.RegisterFindDialog="True" Grid.Row="2" telerik:RadPdfViewerAttachedComponents.RegisterSignaturePropertiesDialog="True" telerik:RadPdfViewerAttachedComponents.RegisterContextMenu="True"/>
<Grid>
And here code behind:
public partial class Page2 : Page, INotifyPropertyChanged
{
public Page2()
{
InitializeComponent();
DataContext = this;
}
private string _pathOfPdf= #"D:\MyFile.pdf";
public string PathOfPdf
{
get{ return _pathOfPdf; }
set{
if (_pathOfPdf != value)
{
_pathOfPdf = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
If I'm not using Biding it works fine. I if I do(on XAML):
DataContext="D:\MyFile.pdf" it shows the pdf
You need to either set the DataContext of the control or the source of the binding to the Page where the source property is defined:
<telerik:RadPdfViewer x:Name="pdfViewer"
DocumentSource="{Binding Path=PathOfPdf, RelativeSource={RelativeSource AncestorType=Page}}" />
I want to bind my StackPanel component to an object and its properties to elements it the StackPanel
<StackPanel Grid.Column="0" Grid.Row="0" Name="device1" Background="#CC119EDA" DataContext="{Binding}">
<Label FontSize="22" Foreground="White">Desk #1</Label>
<TextBox Text="{Binding Name}" />
</StackPanel>
In code behind
device1.DataContext = new Class { Name = "Name" };
What is wrong with this binding? Thanks
You could try like this. When u set the property to the Object , the UI Thread is not aware of the change , so you need to Implement RaisePropertyChange Mechanism. Using MvvmLight Toolkit is great advantage . Here the window datacontext is set to so could inherit all elements.
public partial class MainWindow : Window, INotifyPropertyChanged
{
private string _name;
public string MyName
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged("MyName");
}
}
public MainWindow()
{
InitializeComponent();
MyName = "Eldho";
this.DataContext = this;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Xaml
<StackPanel>
<Label>Hi,</Label>
<TextBox Text="{Binding MyName}"/>
</StackPanel>
I have an App Bar with some buttons like this
<Page.BottomAppBar>
<AppBar x:Name="bottomAppBar" Padding="10,10,10,10" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button Style="{StaticResource ReadAppBarButtonStyle}" >
</Button>
</StackPanel>
</AppBar>
</Page.BottomAppBar>
I want to bind the button text to a selected item property of a ListView and use an IValueConverter.
I found that the button text is to be set using AutomationProperties.Name
how can I bind this property through XAML or Code.
Thanks
You're right, for some reason the following doesn't work, although the same binding works just fine you use it for e.g. Text property of a TextBox:
<Button Style="{StaticResource SkipBackAppBarButtonStyle}" AutomationProperties.Name="{Binding SelectedItem, ElementName=List}" />
I did manage to get it work by using a property in the view model and binding to it both ListView.SelectedItem and AutomationProperties.Name:
<ListView ItemsSource="{Binding Strings}"
SelectedItem="{Binding SelectedString, Mode=TwoWay}" />
<!-- ... -->
<Button Style="{StaticResource SkipBackAppBarButtonStyle}"
AutomationProperties.Name="{Binding SelectedString}" />
SelectedString should be a property in a view model implementing INotifyPropertyChanged:
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
Strings = new ObservableCollection<string>();
for (int i = 0; i < 50; i++)
{
Strings.Add("Value " + i);
}
}
public ObservableCollection<string> Strings { get; set; }
private string _selectedString;
public string SelectedString
{
get { return _selectedString; }
set
{
if (value == _selectedString) return;
_selectedString = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Is it usable or this doesn't work: to change the Text Box.Text and the property behind to change can a binding of this type be made(i know that this can be made with an event from Text Box, i am looking for some kind of binding that can be made) ?
Should i just use Text Box.Text in my cod?
<TextBox Text="{Binding Path=NumeClient, Mode=TwoWay}" Height="23" HorizontalAlignment="Left" Margin="117,21,0,0" Name="textBox1" VerticalAlignment="Top" Width="249" />
public string NumeClient { get; set; }
If I understand the question correctly, you're asking how to setup a two way binding to the Text property of a TextBox?
<TextBox Text="{Binding Path=YourProperty, Mode=TwoWay}" />
This Makes both your property changes the TextBox and the TextBox changes the property (from MSDN)
Add in your class contructor DataContext = this;
public class Person : INotifyPropertyChanged
{
private string name;
// Declare the event
public event PropertyChangedEventHandler PropertyChanged;
public string PersonName
{
get { return name; }
set
{
name = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("PersonName");
}
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
XAML :
<TextBox Text="{Binding Path=PersonName, Mode=TwoWay}" />
Hope it helps
For a list box in WPF I have this template:
<ControlTemplate x:Key="ListBoxItemControlTemplate1" TargetType="{x:Type ListBoxItem}">
<StackPanel Orientation="Horizontal" Background="Silver">
<CheckBox Content="CheckBox" VerticalAlignment="Center"/>
<Label Content="Label" Padding="5,0" Width="260" VerticalAlignment="Center" Background="#F3D6D6D6" Margin="5,0"/>
<Button Content="Edit" Width="Auto" Padding="1" Margin="2.5,0" HorizontalAlignment="Right" Click="Button_Click"/>
</StackPanel>
</ControlTemplate>
And whenever I press the corresponding button for the listBoxItem I want to modify the label of the same listBoxItem, preferably without using a name if possible.
I was thinking maybe there is a way of saying "use the Label from the parent of this button" which I thought would be the StackPanel, but can't find anything useful on the internet.
I think the better solution is to use a view model with a DataTemplate, once you have the code set up you can re-use it over and over with very little chance of error.
Here is what your view model will look like
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<ItemViewModel> _items;
public ViewModel()
{
_items = new ObservableCollection<ItemViewModel>(new List<ItemViewModel>()
{
new ItemViewModel() { Label = "Item1", IsChecked = false },
new ItemViewModel() { Label = "Item2", IsChecked = true },
new ItemViewModel() { Label = "Item3", IsChecked = true },
new ItemViewModel() { Label = "Item4", IsChecked = false },
new ItemViewModel() { Label = "Item5", IsChecked = false },
});
}
public ObservableCollection<ItemViewModel> Items
{
get
{
return this._items;
}
}
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class ItemViewModel : INotifyPropertyChanged
{
private bool _isChecked = false;
private string _label = "Label";
public ICommand ButtonCommand { get; private set; }
public ItemViewModel()
{
this.ButtonCommand = new DelegateCommand(Com_ButtonCommand);
}
public void Com_ButtonCommand(object parameter)
{
this.Label = "New Label text";
}
public string Label
{
get
{
return this._label;
}
set
{
this._label = value;
this.OnPropertyChanged("Label");
}
}
public bool IsChecked
{
get
{
return this._isChecked;
}
set
{
this._isChecked = value;
this.OnPropertyChanged("IsChecked");
}
}
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
public DelegateCommand(Action<object> execute,
Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
There are 3 classes here, 1 of them a helper.
ViewModel --> Your main ViewModel,
ItemViewModel --> Model for each item,
DelegateCommand --> Allows you to map the button to the view model
your xaml will look like this
<ListBox ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Background="Silver">
<CheckBox IsChecked="{Binding IsChecked}" Content="CheckBox" VerticalAlignment="Center"/>
<Label Content="{Binding Label}" Padding="5,0" Width="260" VerticalAlignment="Center" Background="#F3D6D6D6" Margin="5,0"/>
<Button Command="{Binding ButtonCommand}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Notice the "{Binding}" keyword, this "binds" each datatemplate to a member with that name on its own view model, in this case IsChecked and Label.
To load your ViewModel add the following line to the code-behind in your usercontrol(using MVVM you will rarely touch the code-behind of usercontrols at all).
this.DataContext = new ViewModel();
When its your first time seeing a viewmodel it may seem like a lot of work but its mostly re-usable and is the defacto standard for doing things like this (MVVM), Ive included all necessary code to get you started.
The following class as well as DelegateCommand should be kept for later use, I have already included it in the above snippet
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
I'd recommend you to use a viewmodel in the back. That VM exposes a command that is bound to the button. In addition it exposes a DependencyProperty containing the name for the label. And the label is bound to that property.
Now if you press the button, the command is executed, which changes the label text and via databinding the new text will be updated on the label.
The other option, I wouldn't recommend, is to use FindName to find the Label. Or really bad (but works) is to iterate over the controls using the VisualTreeHelper.
I would navigate the VisualTree to find the parent StackPanel, then search that StackPanel to find a child Label to update.
If you're interested, I have some VisualTreeHelpers posted on my blog that would make this easy:
var parent = VisualTreeHelpers.FindAncestor<StackPanel>((Button)sender);
if (parent == null) return;
var lbl = VisualTreeHelpers.FindChild<Label>(parent);
if (lbl == null) return;
lbl.Content = "Some Text";
This is providing I'm not using the MVVM design pattern. If I were using MVVM, I would be storing the Label.Content property in the ViewModel, and the Button command should point to a Command in the ViewModel, and it should pass it the DataBound item as the CommandParameter so it knows which Label to update.
<ControlTemplate x:Key="ListBoxItemControlTemplate1" TargetType="{x:Type ListBoxItem}">
<StackPanel Orientation="Horizontal" Background="Silver">
<CheckBox Content="CheckBox" VerticalAlignment="Center"/>
<Label Content="{Binding SomeText}" ... />
<Button Content="Edit"
Command="{Binding ElementName=MyListBox, Path=DataContext.EditCommand}"
CommandParameter="{Binding }" />
</StackPanel>
</ControlTemplate>