|
I'm working on an WPF MVVM application. The data entry screen has to have all it's fields disabled until the user clicks "Add" or "Edit", and also the fields cannot become enabled if the user does not have rights to that field.
So, I would like to bind all IsEnabled properties in the XAML to a single method on the ViewModel. I would need to pass in a string value which is the 'key' of the field. Then in the VM would use the key to check the rights. The method would be something like
public bool CanEnableField(string Key)
{
}
A converter would probably not work because that class won't know about the VM and the form's mode (Add/Edit).
I could bind each field's IsEnabled to individual properties on the VM and handle all this in the getter, but that would be a lot of properties in the VM.
Anyone have any thoughts on how to do this?
If it's not broken, fix it until it is
|
|
|
|
|
The best way is to have a bool Property in your VM, to which you caan bind the IsEnabled property of the relevant controls like this:-
VM:
public bool CanEnableField(string Key)
{
}
public bool EnableControls
{
get
{
return enableControls;
}
set
{
if (enableControls != value)
{
enableControls = value;
OnPropertyChanged("EnableControls");
}
}
}
View:
<Label Grid.Row="2" Content="Name : " HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="2,2,2,7" />
<TextBox Grid.Column="1" Grid.Row="2" Margin="2" IsEnabled="{Binding Path=EnableControls}" Text="{Binding Path=SelectedCustomer.Name, ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}" />
Hope this helps
When I was a coder, we worked on algorithms. Today, we memorize APIs for countless libraries — those libraries have the algorithms - Eric Allman
|
|
|
|
|
If you're using .NET 4.0 or 4.5, you can combine a single property with a dynamic object to achieve this:
public interface ICanEnableField
{
bool CanEnableField(string key);
}
public sealed class CanEnableFieldHelper : DynamicObject
{
private readonly ICanEnableField _owner;
public CanEnableFieldHelper(ICanEnableField owner)
{
_owner = owner;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = _owner.CanEnableField(binder.Name);
return true;
}
}
public class YourViewModel : ICanEnableField
{
private readonly CanEnableFieldHelper _helper;
public YourViewModel()
{
_helper = new CanEnableFieldHelper(this);
}
public dynamic CanEnable
{
get { return _helper; }
}
public bool CanEnableField(string key)
{
...
}
}
In you XAML, you can then bind to CanEnable.Key , which will return the result of calling CanEnableField("Key") :
<TextBox IsEnabled="{Binding Path=CanEnable.Field1}" ... />
When you need to change the state, you just need to raise the PropertyChanged event for the CanEnable property.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Thanks, I'll take a look at it
If it's not broken, fix it until it is
|
|
|
|
|
This worked perfect. Thanks!
If it's not broken, fix it until it is
|
|
|
|
|
I have a combo box bound to an ObservableCollection<classmodel>. The entity passed into the view has an instance of a ClassModel. I want to select the item in the combo which matches the entite's ClassModel.
So far im lookping over the ObservableCollection to find the item:
foreach (var jobClass in Classes)
{
if (jobClass.Id == JobRevision.JobClass.Id)
{
SelectedClass = jobClass;
break;
}
}
is there a way to do this without loopping?
Thanks
If it's not broken, fix it until it is
modified 12-Jan-13 21:27pm.
|
|
|
|
|
Can't you bind the SelectedValuePath of the combo to the SelectedJobClass.ID
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Not sure I understand. Can you post an example?
If it's not broken, fix it until it is
|
|
|
|
|
It is just the standard combo binding or am I missing something?
<ComboBox x:Name="cboType" Grid.Row="2" Grid.Column="1" ItemsSource="{Binding AttrTypeList,Mode=TwoWay}"
DisplayMemberPath="AttrType"
SelectedValuePath="AttrTypeID"
SelectedValue="{Binding SelectedAttrCostume.AttrTypeID,Mode=TwoWay}"/>
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Yes, but what are 'AttrType' and 'AttrTypeID' and 'SelectedAttrCostume'? Are they properties on the entities in the AttrTypeList list?
If it's not broken, fix it until it is
|
|
|
|
|
|
Ok, I don't know what's wrong, but I still cannot get this to work...
My combo is bound to an ObservableCollection<lookupmodel>, as in:
private ObservableCollection<LookupModel> _Departments;
public ObservableCollection<LookupModel> Departments
{
get { return _Departments; }
set
{
if (_Departments != value)
{
_Departments = value;
RaisePropertyChanged("Departments");
}
}
}
private LookupModel _SelectedDepartment;
public LookupModel SelectedDepartment
{
get { return _SelectedDepartment; }
set
{
if (_SelectedDepartment != value)
{
_SelectedDepartment = value;
RaisePropertyChanged("SelectedDepartment");
}
}
}
Here is the lookup model:
public class LookupModel : _BaseModel
{
private int _Id = 0;
public int Id
{
get { return _Id; }
set
{
if (_Id != value)
{
_Id = value;
RaisePropertyChanged("Id");
}
}
}
private string _Caption = string.Empty;
public string Caption
{
get { return _Caption; }
set
{
if (_Caption != value)
{
_Caption = value;
RaisePropertyChanged("Caption");
}
}
}
}
And in the vie model I have:
SelectedDepartment = Job.Department;
Job.Department is an instance of a lookup model with the selected department in it.
When I run this, the department is not selected in the combo.
What am I doing wrong here???
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
In my resource file I have:
<!--*************************************************************************
* COLORS & BRUSHES
************************************************************************-->
<Color x:Key="TextForeColor">Black</Color>
<SolidColorBrush x:Key="TextForeColorBrush"
Color="{StaticResource TextForeColor}"/>
<!--*************************************************************************
* BASE STYLES
************************************************************************-->
<Style x:Key="BaseTextBlockStyle"
TargetType="TextBlock">
<Setter Property="FontSize" Value="12" />
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="Foreground" Value="{StaticResource TextForeColorBrush}"/>
<Setter Property="FontStyle" Value="Normal"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
<Style x:Key="TextBlockStyle"
TargetType="TextBlock"
BasedOn="{StaticResource BaseTextBlockStyle}">
<Setter Property="Foreground" Value="{StaticResource DataEnteryTextBlockForeColorBrush}"/>
</Style>
<Style x:Ke
Then in a view I have:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="..\Resources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
and
<!--Job Header Area-->
<GroupBox Header=" Job Information "
Grid.Row="0"
BorderBrush="SteelBlue"
Background="#E2F4FF"
Foreground="SteelBlue"
Height="100"
Margin="5"
FontSize="14"
FontStyle="Italic"
FontWeight="Bold">
<Grid>
<!--Job Number-->
<TextBlock Text="Job #: "
Grid.Row="0"
Grid.Column="0"
Style="{StaticResource TextBlockStyle}"
Margin="5,2,2,5"/>
<TextBlock Text="2013-0001"
Grid.Row="0"
Grid.Column="1"
MinWidth="55"
Style="{StaticResource TextBlockDataDisplayStyle}"
Margin="5,2,2,5"/>
The style on the groupbox is being applied to the TextBlocks and TextBoxes.
The style, color, and brush names are all correct.
Anyone see what Im doing wrong?
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
I'm still very much a novice at XAML, but what does this line refer to?
<Setter Property="Foreground" Value="{StaticResource DataEnteryTextBlockForeColorBrush}"/>
I could not see any definition of DataEnteryTextBlockForeColorBrush .
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
From my deep knowledge of all things xaml (insert sarcasm smiley): When you create a style.xaml file that contains the style for DataEnteryTextBlockForeColorBrush. you can reference it via the app.xaml (Silverlight) and it becomes a static resource available to all views. You can also create the style in the view's xaml as a resource (grid.resource/usercontrol.resouce etc) and it becomes a static resource usable by that view only.
Hang on you answer more of these than I do!
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
As I said: "I'm still very much a novice at XAML". Pete O'Hanlon could answer this without drawing breath.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
In my project it's defined above the XAML I pasted. I didn't include it to save space
If it's not broken, fix it until it is
|
|
|
|
|
Following example I managed to get fire both a RoutedEvent and an AttachedEvent from "GrandChild" and have them handled in "MainWindow" two levels up - but I am now confused what's difference between the two? Except how they are declared in "GrandChild". I want to add that both use "RegisterRoutedEvent" but RoutedEvent has a CLR wrapper
References:
http://weblogs.asp.net/vblasberg/archive/2010/03/30/wpf-routed-events-bubbling-several-layers-up.aspx
http://chuckhays.net/blog/2010/05/21/very-simple-routed-event-example/comment-page-1/#comment-1021
http://en.csharp-online.net/WPF_Concepts%E2%80%94Routed_Events_in_Action
MainWindow - Top Level
<window x:class="RoutedEventDemo.MainWindow"
="" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:RoutedEventDemo" title="MainWindow" height="350" width="525" background="DimGray" local:grandchild.grandchildroutedevclick="GrandChild_GrandChildRoutedEvClick">
<stackpanel local:grandchild.grandchildattachedevclick="GrandChildAttachedEvClickHandler">
<Label>Main Window</Label>
<local:middlechild>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void GrandChild_GrandChildRoutedEvClick(object sender, RoutedEventArgs e)
{
string Message = "MainWindow - GrandChildRoutedEvClickEvent handler - Source=" + Convert.ToString(e.Source);
MessageBox.Show(Message);
e.Handled = false;
return;
}
private void GrandChildAttachedEvClickHandler(object sender, RoutedEventArgs e)
{
string Message = "MainWindow - GrandChildAttachedEvClickHandler - Source=" + Convert.ToString(e.Source);
MessageBox.Show(Message);
return;
}
}
MiddleChild - 2nd Level
<usercontrol x:class="RoutedEventDemo.MiddleChild"
="" 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 ="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:RoutedEventDemo" mc:ignorable="d" background="DarkGray" d:designheight="300" d:designwidth="300">
<stackpanel>
<Label>MiddleChild</Label>
<local:grandchild x:name="Junior" verticalalignment="Stretch" grandchildroutedevclick="GrandChild_GrandChildRoutedEvClick">
public partial class MiddleChild : UserControl
{
public MiddleChild()
{
InitializeComponent();
}
private void GrandChild_GrandChildRoutedEvClick(object sender, RoutedEventArgs e)
{
string Message = "MiddleChild - GrandChildRoutedEvClickEvent handler - Source=" + Convert.ToString(e.Source);
MessageBox.Show(Message);
e.Handled = true; // set to true and MainWindow handler won't be triggered
return;
}
}
GrandChild - bottom level
<usercontrol x:class="RoutedEventDemo.GrandChild"
="" 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 ="http://schemas.microsoft.com/expression/blend/2008" mc:ignorable="d" background="LightGray" d:designheight="300" d:designwidth="300">
<stackpanel>
<Label>GrandChild</Label>
<Button Name="btnGrandChild" Click="btnGrandChild_Click_1">Button from GrandChild</Button>
public partial class GrandChild : UserControl
{
#region Routed Event
public static readonly RoutedEvent GrandChildRoutedEvClickEvent = EventManager.RegisterRoutedEvent("GrandChildRoutedEvClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(GrandChild));
// Provide CLR accessors for the event
public event RoutedEventHandler GrandChildRoutedEvClick
{
add { AddHandler(GrandChildRoutedEvClickEvent, value); }
remove { RemoveHandler(GrandChildRoutedEvClickEvent, value); }
}
#endregion
#region Attached Event
public static readonly RoutedEvent GrandChildAttachedEvClickEvent =
EventManager.RegisterRoutedEvent("GrandChildAttachedEvClick",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(GrandChild));
public static void AddGrandChildAttachedEvClickHandler(DependencyObject o, RoutedEventHandler handler)
{
((UIElement)o).AddHandler(GrandChild.GrandChildAttachedEvClickEvent, handler);
}
public static void RemoveGrandChildAttachedEvClickHandler(DependencyObject o, RoutedEventHandler handler)
{
((UIElement)o).RemoveHandler(GrandChild.GrandChildAttachedEvClickEvent, handler);
}
#endregion
public GrandChild()
{
InitializeComponent();
}
private void btnGrandChild_Click_1(object sender, RoutedEventArgs e)
{
this.RaiseEvent(new RoutedEventArgs(GrandChildRoutedEvClickEvent, this));
this.RaiseEvent(new RoutedEventArgs(GrandChildAttachedEvClickEvent, this));
return;
}
}
dev
modified 10-Jan-13 2:24am.
|
|
|
|
|
Good Day
i have a Media Element in WPF and i am playing mp3's programatically on a click of a button. Now there are times where i want to Play two different mp3's in an order after another e.g
PlayAudio("AccountOpen_Message1");
PlayAudio("AccountOpen_Message2");
Now i tried to put it a Thread Sleep between, it work once after that the Second mp3 plays after the first one. So i want to call the same function twice to play different mp3's but i want one to wait for another to finish playing before playing, i hoped for a "isPlaying" Property to determine if the element was playing. Does anyone have a solution.
private void PlayAudio(string Fruit)
{
VideoPlayer.Source = new Uri(@"D:\Articles\How to identify Players in Kinect\IdentifyPlayers\WpfApplication1\WpfApplication1\Voices\" + Fruit + ".mp3", UriKind.Absolute);
VideoPlayer.LoadedBehavior = MediaState.Manual;
VideoPlayer.Play();
}
<MediaElement x:Name="VideoPlayer" Volume="100" LoadedBehavior="Manual" MediaEnded="VideoPlayer_MediaEnded" UnloadedBehavior="Close" ></MediaElement>
private void VideoPlayer_MediaEnded(object sender, RoutedEventArgs e)
{
this.Close();
}
Thanks
Vuyiswa Maseko,
Spoted in Daniweb-- Sorry to rant. I hate websites. They are just wierd. They don't behave like normal code.
C#/VB.NET/ASP.NET/SQL7/2000/2005/2008
http://www.vuyiswamaseko.com
vuyiswa[at]dotnetfunda.com
http://www.Dotnetfunda.com
|
|
|
|
|
Off the top of my head, I would expect that you could use the Position to determine whether or not you've reached the end of the playback.
|
|
|
|
|
hi Pete
The Problem with Position comes if the audio file you are playing is dynamically loaded, the length is unknown.
Vuyiswa Maseko,
Spoted in Daniweb-- Sorry to rant. I hate websites. They are just wierd. They don't behave like normal code.
C#/VB.NET/ASP.NET/SQL7/2000/2005/2008
http://www.vuyiswamaseko.com
vuyiswa[at]dotnetfunda.com
http://www.Dotnetfunda.com
|
|
|
|
|
Hi I have a winforms application I wish to convert to WPF. I have never played in xaml before so looking for a few resources to learn from. I have read a few articles here on this wonderful website and looking for more help. Any suggestions appreciated.
Thank You in advance
Frazzle the name say's it all
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
John F. Woods
|
|
|
|
|
|
Thank You , I just ordered the book.
Frazzle the name say's it all
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.
John F. Woods
|
|
|
|
|
I'd second this book - in fact, have a look at the inside cover and you'll see recommendations from people like Josh, Sacha and me.
|
|
|
|