I have this User control:
I added this user control to my Winforms application (simple BusyIndicator)
UserControl x:Class="Stackoverflow.MyBusyIndicator"
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:xctk="clr-namespace:Xceed.Wpf.Toolkit;assembly=Xceed.Wpf.Toolkit"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<xctk:BusyIndicator x:Name="busyIndicator" IsBusy="{Binding IsBusy}" />
</Grid>
</UserControl>
And all i want is define Method that i can access from c# code in order to stop this indicator.
I believe what you want to do this in the code behind?
public partial class MyBusyIndicator : UserControl
{
public void ToggleIndicator(bool isBusy)
{
// Just an example, in reality you will want to access the BusyIndicator object.
this.IsBusy = isBusy;
}
}
Your XAML code is fine, now just create a Dependency Property and call it "IsBusy", which you then can bind to in your UserControl XAML using a DataBinding (to visually indicate the IsBusy property state),
public partial class BusyIndicator : UserControl
{
public BusyIndicator()
{
InitializeComponent();
}
public bool IsBusy
{
get { return (bool)GetValue(IsBusyProperty); }
set { SetValue(IsBusyProperty, value); }
}
public static readonly DependencyProperty IsBusyProperty =
DependencyProperty.Register("IsBusy", typeof(bool), typeof(BusyIndicator),
new PropertyMetadata(false));
}
Try this :
<UserControl x:Class="Stackoverflow.MyBusyIndicator"
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:xctk="clr-namespace:Xceed.Wpf.Toolkit;assembly=Xceed.Wpf.Toolkit"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<xctk:BusyIndicator x:Name="myBusyIndicator" IsBusy="True" />
</Grid>
</UserControl>
Code Bahind :
namespace Stackoverflow
{
using System;
using System.Windows;
using System.Windows.Controls;
public partial class MyBusyIndicator : UserControl
{
public MyBusyIndicator()
{
this.InitializeComponent();
}
public void ShowIndicator(bool isBusy)
{
this.myBusyIndicator.IsBusy = isBusy;
}
}
}
If you have to access it through code-behind first provide a name attribute to the BusyIndicator control through Xaml first:
<xctk:BusyIndicator IsBusy="True" x:Name="busyIndicator" />
In your code behind create a method as below:
void SetIndicator(bool isBusy)
{
this.busyIndicator.IsBusy = isBusy;
}
If you are using MVVM bind your control's IsBusyProperty IsBusy={Binding IsBusy}
<xctk:BusyIndicator IsBusy={Binding IsBusy} />
And in your viewmodel define IsBusy property and create method as below:
void SetIndicator(bool isBusy)
{
IsBusy = isBusy;
}
So next time you want to set is as True call SetIndicator(true) or if you want to set it as false call SetIndicator(false).
Related
So I have a user interface which has several controls which I want to persist. One of these controls is a button that is supposed to swap between a view and an edit mode. Each of these will have many controls in them that will need to be accessible later on. My main page is defined as follows, with irrelevant stuff stripped down of course.
MapView.xaml
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TripPhotoMapper"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Maps="using:Windows.UI.Xaml.Controls.Maps"
x:Class="TripPhotoMapper.MapView"
mc:Ignorable="d">
<Grid x:Name="grid_main">
<Maps:MapControl x:Name="map_main" MapTapped="MapUserTapped"/>
<StackPanel x:Name="stack_edit_mode">
<Border Tapped="ButtonEditMode">
<TextBlock Text="Edit Mode"/>
</Border>
</StackPanel>
<Grid x:Name="grid_swap_interface">
here is where I want the swapable interfaces
</Grid>
</Grid>
</Page>
MapView.xaml.cs
namespace TripPhotoMapper
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MapView : Page
{
private EditMode _mode_edit;
private ViewMode _mode_view;
private Control _mode_current;
public MapView()
{
this.InitializeComponent();
_mode_edit = new EditMode();
_mode_view = new ViewMode();
_mode_current = _mode_view;
grid_swap_interface.Children.Add(_mode_current);
}
public static class GlobalVars
{
...
//this keeps track on if we are in edit mode
public static bool glo_edit_mode = false;
}
...
private void MapUserTapped(MapControl sender, MapInputEventArgs args)
{
...
//this is the problem
ViewMode.txtblc_view_mode.Text = "hi";
}
//editing controls
private void ButtonEditMode(object sender, TappedRoutedEventArgs e)
{
grid_swap_interface.Children.Clear();
if (GlobalVars.glo_edit_mode == false)
{
_mode_current = _mode_edit;
}
else
{
_mode_current = _mode_view;
}
grid_swap_interface.Children.Add(_mode_current);
}
}
}
I then have two other very barebones xaml files for the two interfaces.
EditMode.xaml
<UserControl
x:Class="TripPhotoMapper.EditMode"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TripPhotoMapper"
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>
<Button/>
</Grid>
</UserControl>
ViewMode.xaml
<UserControl
x:Class="TripPhotoMapper.ViewMode"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TripPhotoMapper"
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>
<TextBlock x:Name="txtblc_view_mode" Text="view mode"/>
</Grid>
</UserControl>
I haven't touched the C# for either of these two additional xaml's yet. So they're just like this.
EditMode.xaml.cs
namespace TripPhotoMapper
{
public sealed partial class EditMode : UserControl
{
public EditMode()
{
this.InitializeComponent();
}
}
}
So I've figured out how to swap between the two interfaces without any issue; the button and textblock do both appear as they should. However, I included (for testing) a function to change the text in txtblc_view_mode to "hi", but I'm given the following error:
'ViewMode.txtblc_view_mode' is inaccessible due to its protection level
I'm incredibly new to splitting up files like this and I can't figure out how to fix it. I've found something mentioned in a few posts
x:FieldModifier="public"
but I don't know where to put it. Could anyone help me? Once the interfaces are properly split up, a lot of controls in each will have to be modified in code and thus I'll need to fix this problem.
Can't try this for now but you can check it out.
Add/modify the following code in your ViewMode cs:
public sealed partial class ViewMode : UserControl
{
public static ViewMode Current { get; private set; }
public ViewMode()
{
this.InitializeComponent();
Current = this;
}
}
And maintain the x:FieldModifier="public" in your desired control (TextBlock) to be edited/modified.
<TextBlock x:Name="txtblc_view_mode" x:FieldModifier="public" Text="view mode"/>
On EditMode cs, add in your methods:
public void ChangeTxtBlockText()
{
TextBlock tb = ViewMode.Current.txtblc_view_mode as TextBlock;
if (tb != null)
{
tb.Text = "Hi";
}
}
In a WPF project (code below) I have a UserControl of type MyUserControl with a dependency property, called MyOrientation of type Orientation.
On the MainWindow I have 2 instances of MyUserControl, where via XAML I set the Orientation property on one to be Horizontal and the other instance to be Vertical.
I have made the MyOrientation property a DP as I want the ability to set it directly in XAML as in this example or using a binding.
My problem is that when I run the project both instances of the UserControl show up with the Orientation = Horizontal?
Could someone please tell me what I am doing wrong and how to fix it?
Many thanks in advance.
Here is the code:
MYUSERCONTROLVIEWMODEL:
public class MyUserControlViewModel : ViewModelBase
{
private Orientation _myOrientation;
public Orientation MyOrientation
{
get { return _myOrientation; }
set
{
if (_myOrientation == value)
return;
_myOrientation = value;
OnPropertyChanged();
}
}
}
MYUSERCONTROL.XAML
<UserControl x:Class="TestUserControlDPProblem.MyUserControl"
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:TestUserControlDPProblem"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="root">
<Grid.DataContext>
<local:MyUserControlViewModel/>
</Grid.DataContext>
<StackPanel Orientation="{Binding MyOrientation}">
<TextBlock>Hello</TextBlock>
<TextBlock>There</TextBlock>
</StackPanel>
</Grid>
MYUSERCONTROL CODE BEHIND:
public partial class MyUserControl : UserControl
{
MyUserControlViewModel _vm;
public MyUserControl()
{
InitializeComponent();
_vm = root.DataContext as MyUserControlViewModel;
}
public static readonly DependencyProperty MyOrientationProperty = DependencyProperty.Register("MyOrientation", typeof(Orientation), typeof(MyUserControl), new FrameworkPropertyMetadata(Orientation.Vertical, new PropertyChangedCallback(OnMyOrientationChanged)));
private static void OnMyOrientationChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
var myUserControl = o as MyUserControl;
myUserControl?.OnMyOrientationChanged((Orientation)e.OldValue, (Orientation)e.NewValue);
}
protected virtual void OnMyOrientationChanged(Orientation oldValue, Orientation newValue)
{
_vm.MyOrientation = newValue;
}
public Orientation MyOrientation
{
get
{
return (Orientation)GetValue(MyOrientationProperty);
}
set
{
SetValue(MyOrientationProperty, value);
}
}
}
MAINWINDOW.XAML
<Window x:Class="TestUserControlDPProblem.MainWindow"
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"
xmlns:local="clr-namespace:TestUserControlDPProblem"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel>
<local:MyUserControl Margin="10" MyOrientation="Horizontal"/>
<local:MyUserControl Margin="10" MyOrientation="Vertical"/>
</StackPanel>
</Grid>
The "internal" view model of the UserControl makes no sense and should not be there. You should instead bind directly to the dependency property by means of a RelativeSource or ElementName Binding:
<StackPanel Orientation="{Binding MyOrientation,
RelativeSource={RelativeSource AncestorType=UserControl}}">
You wouldn't even need the PropertyChangedCallback:
public partial class MyUserControl : UserControl
{
public MyUserControl()
{
InitializeComponent();
}
public static readonly DependencyProperty MyOrientationProperty =
DependencyProperty.Register(
nameof(MyOrientation), typeof(Orientation), typeof(MyUserControl),
new FrameworkPropertyMetadata(Orientation.Vertical));
public Orientation MyOrientation
{
get { return (Orientation)GetValue(MyOrientationProperty); }
set { SetValue(MyOrientationProperty, value); }
}
}
I have one dll which contains the wpf user control.
I have one wpf window in another wpf project which contains the above user control in that.
I have two public properties in wpf user control.
I want to set those properties from the wpf window in which wpf user control is added.
I have tried to do it using dependency property as follows :
TestUserControl.xaml :-
<UserControl x:Class="TestDependencyProperty.TestUserControl"
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>
<Label Content="test property" x:Name="lblTestProperty"/>
</Grid>
</UserControl>
TestUserControl.xaml.cs :-
using System.ComponentModel;
using System.Windows;
namespace TestDependencyProperty
{
/// <summary>
/// Interaction logic for TestUserControl.xaml
/// </summary>
public partial class TestUserControl
{
public TestUserControl()
{
InitializeComponent();
SetLabelText();
}
private void SetLabelText()
{
lblTestProperty.Content = TestProperty;
}
public static readonly DependencyProperty TestDependencyProperty =
DependencyProperty.Register("TestProperty",
typeof(string),
typeof(TestUserControl));
[Bindable(true)]
public string TestProperty
{
get
{
return (string)this.GetValue(TestDependencyProperty);
}
set
{
this.SetValue(TestDependencyProperty, value);
}
}
}
MainWindow.xaml :-
<Window x:Class="TestDependencyProperty.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="clr-namespace:TestDependencyProperty"
>
<Grid>
<local:TestUserControl x:Name="ucTest" TestProperty="HelloWorld"/>
</Grid>
</Window>
I am expecting a label with content "HelloWorld".
So can anybody tell me how to do it ?
Thanks.
User Control XAML:
<UserControl x:Class="TestDependencyProperty.TestUserControl"
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:WpfApplication3"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Label Content="{Binding TestProperty}" x:Name="lblTestProperty"/>
</Grid>
</UserControl>
User Control Code:
public partial class TestUserControl : UserControl
{
public TestUserControl()
{
InitializeComponent();
}
public static readonly DependencyProperty TestDependencyProperty =
DependencyProperty.Register("TestProperty",
typeof(string),
typeof(TestUserControl));
[Bindable(true)]
public string TestProperty
{
get
{
return (string)this.GetValue(TestDependencyProperty);
}
set
{
this.SetValue(TestDependencyProperty, value);
}
}
}
You do not need SetLabelText();
Window Hosting User Control
<local:TestUserControl TestProperty="Test Text" x:Name="MyNewUserControl" />
in code behind if needed:
MyNewUserControl.TestProperty="New Value";
Dependency Properties have change notification built in to them so once a property is bound to them it will automatically get updated when the property does.
I have read through a few articles on this and I can't see what im doing wrong here could anyone help :)
I have a UserControl called CreateRuleItemView I want to add a Dependency Property on here that I can bind my ViewModel too. So far I have.
public partial class CreateRuleItemView : UserControl
{
public CreateRuleItemView()
{
InitializeComponent();
}
public Boolean ShowEditTablePopup
{
get
{
return (Boolean)this.GetValue(ShowEditTablePopupProperty);
}
set
{
this.SetValue(ShowEditTablePopupProperty, value);
}
}
public static readonly DependencyProperty ShowEditTablePopupProperty = DependencyProperty.Register("ShowEditTablePopup", typeof(Boolean), typeof(CreateRuleItemView), new PropertyMetadata(null, OnShowEditTablePopupChanged));
private static void OnShowEditTablePopupChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
}
}
If I then try to access the property in the User Control Xaml I get:
<UserControl x:Class="Views.Setup.CreateRuleItemView"
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"
d:DataContext="{d:DesignInstance Type=vm:CreateRuleItemViewModel, IsDesignTimeCreatable=False}"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" ShowEditTablePopup="{Binding DataContext.ShowEditTablePopup}" >
Error 1 The member "ShowEditTablePopup" is not recognized or is not accessible.
Error 3 The property 'ShowEditTablePopup' does not exist on the type 'UserControl'
Error 2 The property 'ShowEditTablePopup' was not found in type 'UserControl'.
Edit 1:
Ok Managed to get around this by adding the binding in the code behind on my Main window where i setup my view.
Setup.CreateRuleItemView v = new Setup.CreateRuleItemView();
BindingOperations.SetBinding(v, CreateRuleItemView.EditTablePopupProperty, new Binding("EditTablePopup"));
You won't be able to achieve this with a UserControl (I've just tried replacing the <UserControl... partial declaration in XAML with <local:CreateRuleItemView when recreating the code locally, but this results in a circular reference and thus won't compile/will potentially result in a XamlParseException). I'd write a control inheriting from ContentControl to which you can add the property and template it instead (I did this with WPF so the namespaces may differ, otherwise the code will work):
using System;
using System.Windows;
using System.Windows.Controls;
namespace DepPropTest
{
/// <summary>
/// Description of CreateRuleItemView.
/// </summary>
public class CreateRuleItemView : ContentControl
{
public CreateRuleItemView()
{
}
public static readonly DependencyProperty ShowEditTablePopupProperty =
DependencyProperty.Register("ShowEditTablePopup", typeof (bool), typeof (CreateRuleItemView), new PropertyMetadata());
public bool ShowEditTablePopup
{
get { return (bool) GetValue(ShowEditTablePopupProperty); }
set { SetValue(ShowEditTablePopupProperty, value); }
}
}
}
Then you can use it as follows (this example uses WPF by the way, hence Window being the parent control):
<Window x:Class="DepPropTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DepPropTest"
Title="DepPropTest" Height="300" Width="300">
<local:CreateRuleItemView Width="300"
Height="300"
ShowEditTablePopup="True">
<local:CreateRuleItemView.Template>
<ControlTemplate>
<!-- define your control's visual appearance... -->
</ControlTemplate>
</local:CreateRuleItemView.Template>
<TextBox Text="Some content for your view" />
</local:CreateRuleItemView>
</Window>
Here is my user control(MonthCal)'s code behind.
public partial class MonthCal : UserControl
{
public DayOfWeek StartDayOfWeek { get { return (DayOfWeek)GetValue(StartDayOfWeekProperty); } set { SetValue(StartDayOfWeekProperty, value); } }
public static readonly DependencyProperty StartDayOfWeekProperty = DependencyProperty.Register("StartDayOfWeek", typeof(DayOfWeek), typeof(MonthCellHeader), new UIPropertyMetadata(DayOfWeek.Sunday, StartDayOfWeek_PropertyChanged));
//...
}
and also, here is a xaml of the MonthCal.
<UserControl x:Class="GCDR.MonthCal"
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">
<!-- ... -->
</UserControl>
And so, How can I set the 'StartDayOfWeek' dependency property in xaml? as you guys know, the following code is impossible:
<UserControl ...
StartDayOfWeek="Sunday">
</UserControl>
Please give me a help.
You can not use the dependency property in markup of the UserControl but you can use it when you place instance of the user control somewhere like so:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1">
<Grid>
<local:UserControl1 local:StartDayOfWeek="Friday" />
</Grid>
</Window>
With in your user control you can bind some other property to your dependency property like so:
<UserControl x:Class="WpfApplication1.UserControl1"
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:WpfApplication1"
mc:Ignorable="d" >
<Grid>
<Label Content="{Binding RelativeSource={RelativeSource AncestorType=local:UserControl1},Path=StartDayOfWeek}" />
</Grid>
</UserControl>
Why you cannot set StartDayOfWeek is that UserControl in XAML does not have StartDayOfWeek dependency property, in other word UserControl type is not MonthCal type.
As, in XAML, UserControl is base class of UserControl1, you can define MonthCal inherited UserControl and then declare MonthCal in XAML.
XAML
<local:MonthCal x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication1" Title="MainWindow"
Height="350" Width="525"
StartDayOfWeek="Monday">
<Grid></Grid>
</local:MonthCal>
Codebehinde
namespace WpfApplication1
{
public class MonthCal : Window
{
public DayOfWeek StartDayOfWeek { get { return (DayOfWeek)GetValue(StartDayOfWeekProperty); } set { SetValue(StartDayOfWeekProperty, value); } }
public static readonly DependencyProperty StartDayOfWeekProperty =
DependencyProperty.Register("StartDayOfWeek", typeof(DayOfWeek), typeof(MonthCal), new UIPropertyMetadata(DayOfWeek.Sunday, StartDayOfWeek_PropertyChanged));
private static void StartDayOfWeek_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}
}
public partial class MainWindow : MonthCal
{
public MainWindow()
{
InitializeComponent();
}
}
}