I have a CheckBox like this-
<CheckBox Command="{Binding Command1}"
CommandParameter="{Binding }"
IsChecked="{Binding Prop1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
When I click it - the IsChecked binding is triggered before the Command execution. It doesn't look like it's due to the order they appear in xaml(I can change it and the execution order stays the same).
Now I'm wondering - is there any place that documents the order of execution for Bindings/Commands? Or maybe there's just a simple guiding rule?
Can I count on the IsChecked binding to always trigger before the Command?
Related
I have an xceed:DataGridControl with bounded ItemsSource. Currently I'm trying to set my in/visible columns and the title/headertext for each visible column. Preferably I would like to bind a property in my ViewModel, to set the in/visible columns and theirs titles. But I find no way I could do it. Does anyone know a solution to this problem?
<xceed:DataGridControl
x:Name="dataGridControl"
SelectedItem="{Binding SelectedTextItem, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemsSource="{Binding ItemsSourceData, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" >
</xceed:DataGridControl>
Yes indeed I had to deal with xceed's controls few months ago.
DataGridControl allows you to generate columns automantically. That is also its default behavior.
In order to have your own columns you will have to disable the property AutoCreateColumns and futhermore you will have to set few columns on the property DataGridControl.Columns.
There you will be able to bind Visible property of the Column.
Thanks to Peter for providing this code:
<xceed:DataGridControl ItemsSource="{Binding TextSet}" >
<xceed:DataGridControl.Columns>
<xceed:Column FieldName="ColumnId" Title="{Binding DatagridTitle[ColumnId], Mode=OneWay}" Visible="True" />
</xceed:DataGridControl.Columns>
</xceed:DataGridControl>
I also met similar issue.
You can use the Visible property, then do following:
<xcdg:ColumnFieldName="ColumnId" Title="ColumnId"
Visible="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type typeOfAncestor}}, Path=DataGridControl.DataContext.BooleanSourceProperty}"/>
For example, if the typeOfAncestor is xcdg:MergedColumn and BooleanSourceProperty is IsVisble, then the code should be:
<xcdg:ColumnFieldName="ColumnId" Title="ColumnId"
Visible="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type xcdg:MergedColumn}}, Path=DataGridControl.DataContext.IsVisible}"/>
Then the issue can be solved.
I have a ListBox ItemTemplate where I have a CheckBox that is Binded to a List<> that I am maintaining in my application.
My XAML:
<ListBox x:Name ="lstTasks">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="30,12,0,0">
<CheckBox IsChecked="{Binding use}" Unchecked="CheckBox_Unchecked" Tag="{Binding key}" Checked="CheckBox_Checked" />
<TextBlock Width="160" Text="{Binding key}" Margin="20,18,0,0" />
<TextBlock Text="{Binding value}" Margin="0,18,0,0"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
And :
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
lstTasks.ItemsSource = null;
lstTasks.ItemsSource = a.Words; //a.Words is the List<DataClass>
}
I have observed that the Checked and Unchecked events get fired on its own when I scroll in the list of these Items. I have logic attached to these Events and they mess the whole thing up by checking and unchecking random entries. This starts after I uncheck one of the items. (By default all the items are checked)
I am new to WPF and Windows Phone, what am I doing wrong.?
Firstly, Windows Phone does not use WPF. You are using Silverlight which is based on a sub-set of WPF. They are different technologies with different capabilities. Much of what you can do on one you can't do on the other.
It would help to see more of your code, particularly the viewmodel to get a complete picture of what's going on.
I suspect one of two things though:
1 - there is some logic somewhere based on the setting of the use property and as this is changed in the vm, the fact it is reflected in the UI and that triggers the events.
2 - You have a virtualized list inside your ListBox and as items are loaded it's triggering the UI updates (due to the binding) and that in turn is triggering the events.
Without being able to see more code it's hard to be more specific.
As an alternative to this approach you could use a 2-way binding of the use property and move the logic from your event handlers (for checked and unchecked) and into the property setter.
I have a WPF/MVVM (using MVVM-Light) app setup with a ComboBox that is inside a DataTemplate. The XAML of the ComboBox looks like this:
<ComboBox x:Name="cbTeachers"
Grid.Column="1"
Style="{StaticResource ComboBox}"
ItemsSource="{Binding Teachers}"
Grid.Row="3"
DisplayMemberPath="Name"
SelectedValuePath="Id"
IsSynchronizedWithCurrentItem="False"
SelectedItem="{Binding Path=SelectedTeacher}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding TeacherSelectedCommand}"
CommandParameter="{Binding SelectedItem, ElementName=cbTeachers}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
The Teachers property for the ItemsSource is a type called ObservableRangeCollection and is based on the code found here: http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx, but it's very similar to a standard ObservableCollection. The SelectedTeacher property is set when another property is set and the code looks very similiar to this:
this.SelectedTeacher = (from t in this.Teachers where t.Id == this.DataItem.Teacher.Id select t).Single();
The problem I am running into, which makes zero sense to me, is SelectedTeacher is getting reset to null once I set it. I can step through the debugger and see SelectedTeacher has a value and when I put a breakpoint on the setter for the property it definitely has the value. But then that property gets hit again with a null value. I checked the call stack and it showed the only preceeding line as being External Code (which makes sense since I only set that property in one place and it only gets hit once, as expected). Expanding the External Code option in the call stack window shows the typical WPF call stack of maybe 40 methods so it's definitely internal to WPF and not something I am doing to make it reset. In fact, when I remove the SelectedItem="{Binding SelectedTeacher}" the setter for that property doesn't get called a second time (thus it retains its value), but of course the ComboBox doesn't show the selected item either. I tried implementing a SelectedIndex option in my viewmodel but that didn't work either. The ComboBox just won't select the item. I can change the selected item in the ComboBox just fine, but the initial setting won't take.
Any ideas? Based on everything I've searched it might be related to me using a DataTemplate, but I have to because that template is part of a parent ContentTemplateSelector implementation.
As a side note, I have multiple properties that bind to controls in this DataTemplate and this is the only one that doesn't work. The others work perfectly. I have also tried the ComboBox with and without the "IsSynchronizedWithCurrentItem" flag and it made no difference.
have you tried to remove to EventTrigger stuff and just to use
SelectedItem="{Binding Path=SelectedTeacher, Mode=TwoWay}"
with Mode=TwoWay?
its not clear to me what you want to achieve with your EventTrigger?
What exactly I want to do is that there are 2 tables,ie, user and userprofile and both of them have almost identical fields. I shall take example of the email field. There is a textbox and the User table email field value is displayed in it. What I want to do is, have a context menu such that when the user right clicks on the textbox, the menu displays both the User and UserProfile email field values. – developer 1 hour ago
Whatever value one selects from the context menu the textbox then displays that value. You can use Binding Email1 and Binding Email2, as I have no problems getting those two values from database so I shall change my code accordingly. As I am new to WPF and .NET framework itself, I am not sure how to achieve this. Please let me know if I have made myself clear this time.
I am not sure how to handle commands and events. Can anybody show me the code to accomalish this..
<TextBox Style="{StaticResource FieldStyle}" Text="{Binding Email1, UpdateSourceTrigger=PropertyChanged}">
<TextBox.BorderBrush>
<MultiBinding Converter="{StaticResource TextBoxBorderConverter}">
<Binding Path="Email1"/>
<Binding Path="Email2"/>
</MultiBinding>
</TextBox.BorderBrush>
</TextBox>
Thanks in advance
At risk of giving you a WPF/MVVM noob answer and getting flamed, here goes. I can't advise you on databinding with databases since I've never done it, so I will just give you the XAML and it's up to you to work on the database end.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<TextBox Height="28" Text={Binding PreferredEmail}">
<TextBox.ContextMenu>
<ContextMenu>
<MenuItem Header="{Binding Email1}" Command="{Binding Email1Command}" />
<MenuItem Header="{Binding Email2}" Command="{Binding Email2Command}" />
</ContextMenu>
</TextBox.ContextMenu>
</TextBox>
</Grid>
</Page>
In the databinding to objects case, PreferredEmail, Email1, and Email2 would bind to a dependency property or a property that raises the PropertyChanged event. This is how your ViewModel (or whatever you want to call the lower-level code) will update the data. If you change those values in code-behind, ultimately it'll get reflected in the context menu automagically. Then you have to implement two ICommand-based classes to handle the setting of PreferredEmail.
I think it's super lame to implement two command handlers, and it certainly won't scale well if you have to add more email sources. I think a better solution would be to use one command handler and a CommandParameter that is the selected MenuItem header, but I don't know how to do that. But in any case, the two command handler solution will still work if you're in a bind.
Is it possible to disable a button in a DataGridTemplateColumn? I have a DataGridTemplate as follows:
<toolkit:DataGridTemplateColumn Header="Timer" Width="50">
<toolkit:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Start" Click="Button_Click" CommandParameter="{Binding}" />
</DataTemplate>
</toolkit:DataGridTemplateColumn.CellTemplate>
</toolkit:DataGridTemplateColumn>
The purpose of the Button is to start a timer recorded to the object associated with that row. My timer code works fine but I would also like to disable the buttons of every other row so that you can only have one timer running.
I used
WorkItemGrid.Columns[WorkItemGrid.Columns.Count - 1].GetCellContent(item).IsEnabled = false
to disable it and all the buttons correctly appear disabled but if you click on the button twice it will reenable and allow you to click on it a third time and trigger the Click event. Is it possible to actually disable the button?
I would have the object the Datagrid is bound to expose a "IsEnabled" boolean property I can bind the button to. Whenever the handler is called, simply get the other object from your original collection and have them change their property to false. This will automatically disable the other buttons.
If your are not in control of the "timer" class, you can wrap it in your own class before databinding the grid to the collection of your objects.
If it is acceptable to disable the button that was clicked in addition to the others, then I would bind Button.IsEnabled to a property that is set to false once the timer is started, and then change it back to true once the operation has finished.
If that is not acceptable, then I'm not sure if there is a way to do this, since by definition the template is used to create the controls in each row. Well, you could search the visual tree for all the other buttons, but that just doesn't seem like a good thing to do (not to mention it could be slow for a large amount of data).
its not working in my case.
<DataGridTemplateColumn Width="70" Header="Refund" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button x:Name="btnRefundGame" IsEnabled="{Binding RESUND_STATUS}" CommandParameter="{Binding Path=IDEN_LOGID}" Content="Refund" Click="btnRefundGame_Click" ></Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>