XAML TextBox isReadOnly Binding - c#

I am trying to make a textbox read only using Binding in Windows 8.1 apps. I have tried some code from the internet which does not work.
Can you suggest any simplest way to do it, I am very new to the concept Binding.
XAML
<TextBox x:Name="tbOne" IsReadOnly="{Binding Path=setread, Mode=OneWay}" />
<Button Content="isReadonlyBinding" x:Name="isReadonlyBinding" Click="isReadonlyBinding_Click"></Button>
XAML.CS
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register(
"setread",
typeof(bool),
typeof(MainPage),
new PropertyMetadata(false)
);
public bool setread
{
get { return (bool)GetValue(IsReadOnlyProperty); }
set { SetValue(IsReadOnlyProperty, value); }
}
private void isReadonlyBinding_Click(object sender, RoutedEventArgs e)
{
setread = true;
}

try this.
<page X:name="PageName">
IsReadOnly="{Binding ElementName=PageName,Path=setread, Mode=OneWay}"

Implement INotifyPropertyChanged on your code behind. Then modify the property as follows:
private bool _setread;
public bool Setread
{
get { return _setread; }
set {
if(_seatread == value) return;
_setread = value;
RaisePropertyChanged("Setread");
}
}
Give a name to root element like x:Name="root", and bind to Setread with ElementName=page. Note that it is much better to prepare a view model. A view-model-code-behind is just a quick workaround.

Related

Custom UserControl DependencyProperty Binding

I created a custom UserControl where among other controls I have the following
<TextBlock Text="{Binding NameUtility}" />
<TextBlock Text="{Binding TotalCost}" "/>
In the code both binding are declared as follows
public static readonly DependencyProperty SetNameUtilityProperty =
DependencyProperty.Register(
nameof(NameUtility),
typeof(string),
typeof(SummaryInfo));
public string NameUtility
{
get { return (string)GetValue(SetNameUtilityProperty); }
set { SetValue(SetNameUtilityProperty, value); }
}
public static readonly DependencyProperty SetTotalCostProperty =
DependencyProperty.Register(
nameof(TotalCost),
typeof(string),
typeof(SummaryInfo));
public string TotalCost
{
get { return (string)GetValue(SetTotalCostProperty); }
set { SetValue(SetTotalCostProperty, value); }
}
The above control is used in another control XAML as
<Utilities:SummaryInfo NameUtility="GAS" TotalCost="{Binding TotalGasEuro}"/>
The binded variable TotalGasEuro is correctly declare as follows
private string _totalGasEuro;
public string TotalGasEuro { get => _totalGasEuro; set { _totalGasEuro = value; NotifyPropertyChanged(); } }
When running the app, GAS shows up, while the binded value, which is updated on runtime, does not. (I removed from the code above graphical portions)
I found out my problem.
Looks like to have a binding as the one I was trying to achieve, you need to specify the relative source.
In my case when calling the custom control from XAML:
<Utilities:SummaryInfo NameUtility="GAS" TotalCost="{Binding TotalGasEuro, RelativeSource={RelativeSource AncestorType=UserControl}}"/>

DependencyProperty callback not called

I'm currently doing an usercontrol with C#/WPF and i'm using some DependencyProperty objects.
What I want to do is when the value changes, we call a callback method to process some data... I saw that there is a PropertyChangedCallback class for this purpose, but it doesn't work..
Here's my code:
UserControl:
public partial class TimeLine : UserControl
{
public static readonly DependencyProperty FramecountProperty = DependencyProperty.Register("FrameCount", typeof(Int32), typeof(TimeLine), new FrameworkPropertyMetadata(0, new PropertyChangedCallback(FrameCountChanged)));
public Int32 FrameCount
{
get { return (Int32)this.GetValue(FramecountProperty); }
set { this.SetValue(FramecountProperty, value); }
}
// More code...
public static void FrameCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Do stuff
}
}
xaml:
<!-- Time line container -->
<controls:TimeLine Grid.Row="2" Header="Storyboard" FrameCount="{Binding FrameCount}" />
ViewModel:
private Int32 frameCount;
public Int32 FrameCount
{
get { return this.frameCount; }
// this is from: https://github.com/ShyroFR/CSharp-Elegant-MVVM
set { this.NotifyPropertyChanged(ref this.frameCount, value); }
}
public MainViewModel()
{
this.FrameCount = 42;
}
I'm I doing it the wrong way?
Thanks for your help.
I've found a solution, by finding the ancestor.
<controls:TimeLine Grid.Row="2" Header="Storyboard" FrameCount="{Binding Path=DataContext.FrameCount, Mode=TwoWay, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" />
Thanks for your help!
Add Mode=TwoWay to your binding. By default binding for custom dependency properties are OneWay.

"AttachedProperty" PropertyChangedCallback never calls for my LayoutAnchorable, but works on DockingManager. AvalonDock

I am trying to use AttachedProperty in my AvalonDock, I want it to be part of LayoutAnchorable but PropertyChangedCallback never get called. i have binded AttachedPropert and i am getting the control over ViewModel ie: when binded property changes it trigger my ViewModel Property.
My AttachedProperty
public static readonly DependencyProperty IsCanVisibleProperty =
DependencyProperty.RegisterAttached("IsCanVisible", typeof(bool), typeof(AvalonDockBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(IsCanVisiblePropertyChanged)));
private static void IsCanVisiblePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
LayoutAnchorable control = d as LayoutAnchorable;
if (control != null)
{
control.IsVisible = (bool)e.NewValue;
}
}
public static void SetIsCanVisible(DependencyObject element, bool value)
{
element.SetValue(IsCanVisibleProperty, value);
}
public static bool GetIsCanVisible(DependencyObject element)
{
return (bool)element.GetValue(IsCanVisibleProperty);
}
XAML
<xcad:DockingManager>
<xcad:LayoutRoot >
<xcad:LayoutPanel Orientation="Horizontal" >
<xcad:LayoutAnchorablePane >
<xcad:LayoutAnchorable Title="Folder" behv:AvalonDockBehaviour.IsCanVisible="{Binding IsHideExplorer, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
<Views:ExplorerView DataContext="{Binding ExplorerViewModel}"/>
</xcad:LayoutAnchorable>
</xcad:LayoutAnchorablePane>
</xcad:LayoutPanel>
</xcad:LayoutRoot>
</xcad:DockingManager>
ViewModel Property
private bool _IsHideExplorer;
public bool IsHideExplorer
{
get { return _IsHideExplorer; }
set { _IsHideExplorer = value; NotifyPropertyChanged(); }
}
I have tried attaching the property to DockingManager the PropertyChangedCallback works. Any Help guys.
Did you already check the DataContext of your LayoutAnchorable? Maybe the DataContext is not passed down to it. In that case the Binding would not work and your DependencyProperty is not updated.

WP8 LongListMultiSelector Binding SelectedItems

I have a question concerning the LongListMultiSelector in the Windows Phone 8 Toolkit.
I want to use this control to implement a file browser in WP8 (using MVVM). Since the SelectedItems property is not bindable, I used the solution in this article to fix that.
http://dotnet-redzone.blogspot.de/2012/11/windows-phone-8longlistselector.html
Here's my relevant code:
XAML
<Grid DataContext="{Binding FileBrowserViewModel}">
<local:LongListMultiSelector
x:Name="FileList"
ItemsSource ="{Binding CurrentFileList}"
EnforceIsSelectionEnabled="{Binding IsInSelectionMode}"
toolkit:TiltEffect.IsTiltEnabled="True"
SelectedItems="{Binding SelectedFiles, Mode=TwoWay}"
IsSelectionEnabled="True"/>
</Grid>
My LonglistMultiSelector
public class LongListMultiSelector : Microsoft.Phone.Controls.LongListMultiSelector
{
public LongListMultiSelector()
{
SelectionChanged += LongListMultiSelector_SelectionChanged;
}
void LongListMultiSelector_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
this.SelectedItems = base.SelectedItems;
}
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register(
"SelectedItems",
typeof(object),
typeof(LongListMultiSelector),
new PropertyMetadata(null, OnSelectedItemsChanged)
);
private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var selector = (LongListMultiSelector) d;
selector.SelectedItems = e.NewValue;
}
public new object SelectedItems
{
get { return GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
}
}
VIEW MODEL
/// <summary>
/// The currently selected Items.
/// </summary>
public ObservableCollection<File> SelectedFiles
{
get { return _selectedFiles; }
set { Set(() => this.SelectedFiles, ref _selectedFiles, value); }
}
private ObservableCollection<File> _selectedFiles;
But this solution does not work. The SelectedFiles Property does not change at all. (_selectedFiles is always null)
Edit: Set(() => this.SelectedFiles, ref _selectedFiles, value); is from the Mvvmlight (Laurent Bugnion) package.
I solved my problem with using a normal LongListSelector and giving each Item inside it a Boolean IsSelected.
The DataTemplate then has a checkbox that looks like this:
<CheckBox IsChecked="{Binding IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}"/>

Create a proxy for a dependency property

I am trying to create a simple dependency property proxy. I made a custom control, it's a file picker, which is made off a textbox (name: "TextBox_FilePath") and a button showing the open file dialog.
As I am making a reusable control I'd like it to have a "SelectedFilePath" property. As the Text property seems to be perfect for my control to be the "SelectedFilePath" property, I'd just like to proxy these dependency property.
The first approach I made was:
public static readonly DependencyProperty SelectedFilePathProperty = TextBox.TextProperty;
public string SelectedFilePath
{
get { return (string) this.TextBox_FilePath.GetValue(SelectedFilePathProperty); }
set { this.TextBox_FilePath.SetValue(SelectedFilePathProperty, value); }
}
which worked, but throwed an exception when trying to bind to that property. Then I came off with:
public static readonly DependencyProperty SelectedFilePathProperty =
DependencyProperty.Register("SelectedFilePath", typeof (string), typeof (FilePicker), new PropertyMetadata(default(string)));
public string SelectedFilePath
{
get { return (string) this.TextBox_FilePath.GetValue(SelectedFilePathProperty); }
set { this.TextBox_FilePath.SetValue(SelectedFilePathProperty, value); }
}
which does work, but I've got no idea why?! Where did I specify I wanted the text property of the textbox?
What am I missing to simply proxy out that dependency property?
EDIT:
The solution with AddOwner doesn't work too, it throws an Excetion saying "binding can only be applied on a dependency property". Code:
public static readonly DependencyProperty SelectedFilePathProperty =
TextBox.TextProperty.AddOwner(typeof(FilePicker));
public string SelectedFilePath
{
get { return (string)this.TextBox_FilePath.GetValue(SelectedFilePathProperty); }
set { this.TextBox_FilePath.SetValue(SelectedFilePathProperty, value); }
}
What don't I understand?
EDIT2:
For everybody else having issues understanding the answer, I've made a little graphic
The first approach does not work because the property is registered only for the TextBox, adding a reference in another class does nothing.
The second one just creates a whole new string property.
If you really want to reuse the TextBox.TextProperty call AddOwner on it.
e.g.
public static readonly DependencyProperty SelectedFilePathProperty =
TextBox.TextProperty.AddOwner(typeof(FilePicker));
(Note that this property is registered as "Text", so you probably should just create a new property with the name you want as you did already. I would also recommend to set metadata flags to bind two-way by default if you want to have the same binding behaviour as TextBox.Text.)
This solution is a little tricky but works.
Given this user control:
<Grid>
<StackPanel>
<WpfApplication1:FilePicker SelectedFilePath ="{Binding MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBlock Text="{Binding MyProperty}" />
</StackPanel>
</Grid>
And its viewmodel:
public class MainWindowViewModel : INotifyPropertyChanged
{
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string e)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(e));
}
#endregion
private string _myProperty;
public string MyProperty
{
get { return _myProperty; }
set
{
_myProperty = value;
OnPropertyChanged("MyProperty");
}
}
}
XAML for FilePicker control:
<Grid>
<TextBox x:Name="TextBox_FilePath" DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type WpfApplication1:FilePicker}}}" Text="{Binding SelectedFilePath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</Grid>
CodeBehind for FilePicker control:
public partial class FilePicker : UserControl
{
public FilePicker()
{
InitializeComponent();
}
/* private PROXY DP*/
private static readonly DependencyProperty TextProperty =
TextBox.TextProperty.AddOwner(typeof(FilePicker));
/* public DP that will fire getter/setter for private DP */
public static readonly DependencyProperty SelectedFilePathProperty =
DependencyProperty.Register("SelectedFilePath", typeof(string), typeof(FilePicker), new PropertyMetadata(default(string)));
public string SelectedFilePath
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}
Works like a charm.
As I had issues understanding H.B.s answer I made a little graphic which helped me to understand what's going on under the hood. Here it is;
Maybe it helps someone else :)

Categories

Resources