I'm using a telerik RadGridView which is pretty much the same thing as a normal DataGrid in WPF. In my gridview.columns I have a GridViewDataColumn which then allows me to put a celltemplate then a datatemplate and then allow me to put different controls within a grid. I have a combobox and a textbox(only one shows at a time based on visibility property). The problem I'm having is the tab system is kind of weird and doesn't work right. When I tab to a cell in the column above, my combobox nor my textbox ever gets focus. In fact the cell turns completly white. So I was wondering how (in code behind) can I detect when a user tabs in this particular cell and manually set focus to these child elements inside this cell on the selected row?
<telerik:GridViewDataColumn x:Name="MyDataColumn" Focusable="True" GotFocus="MyDataColumn_GotFocus_1" Header="Header1" Width="250">
<telerik:GridViewColumn.CellTemplate>
<DataTemplate>
<Grid>
<Textbox x:name="MyTextbox" Visibility="{Binding IsTextbox}"/>
<Combobox x:name="MyCombobox" Visibility="{Binding IsCombo}"/>
</Grid>
</DataTemplate>
</telerik:GridViewColumn.CellTemplate>
</telerik:GridViewDataColumn>
*Basically, how can I gain access to one of those child controls inside this GridViewDataColumn in code behind so that I can set focus to it? Thanks so much for any advice.
Probably the most straight forward answer to your question can be found by reading the answer to the Access items inside the DataTemplate in WPF post.
However, it may be worth reading the correct answer in this Access Elements inside a DataTemplate… How to for more than 1 DataTemplate? post also.
Related
I am fairly new to WPF and have two questions?
Question #1:
From my XAML snip below, by button "btnRed" word's fine with my code behind. When the button is clicked, the proper view is display. However, how does one perform the same thing "programmatically"? Hence, my next question.
Question #2:
I am not sure how to make a "textbox" and "button" work together to perform the same action. What I'm trying to do is this. (1) I would like the textbox to be linked to the "DataContext" of the button, "btnDisplayView". (2) so when I type in, say, "RedView" into the textbox and click the button, the correct view is displayed.
My long term goal is to have a database, with a couple of tables. A table for "MenuItems" and a table for "Views". Instead of using buttons, I'll use the menu control. Then once a menu item is selected, it would display the correct view.
But for now, I'm startings small and trying to keep it simple:
--------- WPF - XAML START ---------------------------
<StackPanel Grid.Column="0" Orientation="Vertical">
<TextBox x:Name="txtDisplayView" Height="23" Margin="5" TextAlignment="Center"/>
<Button x:Name="btnDisplayView" Content="Display" Margin="5" Click="btnDisplay_Click"/>
<Button x:Name="btnRed" Content="Red" Margin="5" DataContext="RedView" Click="Red_Click"/>
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Vertical">
<ContentControl Margin="5" Content="{Binding}"/>
</StackPanel>
-----------WPF - XAML END -------------------------
If someone could show me how to get this to work, it would help me move my project in the right direction and would be greatly appreciated.
What you need here is:
Create a property in your DataContext that represents the selected item
Bind that property to your TextBox element
Now, you have two options. One is "WPF Friendly" and the other is more Windows Forms-ish:
Create a command (take a look at this article) that reads a parameter, which will be binded to the property you created before
On the Click event, you can read the binded property value
I personally prefer the first solution. Why? Because when you change it to a Menu, for example, your work will be only to populate the menu with your list items (the MenuItem class also has a Command property, so the implementation is the same as with a Button). You will only need to change the source!
In my WPF app we are using an adorner for displaying validation messages, in the particular case there is a single row grid that has multiple controls some of which have validation. The problem I'm having is that I want to force the width of the error message control to be the same as the grid but can't seem to find a way to reference that grid from the adorner template. Here is a sample of what I tried:
<ControlTemplate x:Key="Local_TopAdornedTemplateWide">
<StackPanel>
<AdornedElementPlaceholder x:Name="adornedElement"/>
<TextBlock MaxWidth="{Binding Path=ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType=Grid}, ElementName=adornedElement}"
TextWrapping="Wrap"
Text="{Binding Converter={StaticResource Local_ValidationErrorMessageConverter}}"
Style="{DynamicResource Error_Text}"
Padding="2 1 0 0"
Visibility="{Binding ElementName=adornedElement, Mode=OneWay, Path=AdornedElement.IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"
/>
</StackPanel>
</ControlTemplate>
This causes the application to crash with an XamlParseException.
Ideally the solution would not be specific to a grid so that it would get the width of any container type, but for now grid is the only use case.
Edit:
Here is an example of another template we use in the application; this template would not work for my case as it would limit the error to be the width of a single column of the aforementioned grid:
<ControlTemplate x:Key="Local_TopAdornedErrorTemplate">
<StackPanel>
<AdornedElementPlaceholder x:Name="adornedElement"/>
<TextBlock MaxWidth="{Binding ElementName=adornedElement, Path=ActualWidth}"
TextWrapping="Wrap"
Text="{Binding Converter={StaticResource Local_ValidationErrorMessageConverter}}"
Style="{DynamicResource Error_Text}"
Padding="2 1 0 0"
Visibility="{Binding ElementName=adornedElement, Mode=OneWay, Path=AdornedElement.IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"
/>
</StackPanel>
</ControlTemplate>
Using snoop I captured the following two screenshots (I could not take one of the full stack to prevent posting anything proprietary)
This shot shows the grid I mentioned previously, within this it is the FinancialTextBox item that is being adorned
This shot shows two things, the item selected in blue is the highest ancestor of the grid in the previous shot, the yellow highlight is the Textbox from the content template
With those two it seems to be apparent that (based on information from Contango's answer) the two items aren't not in the same visual tree which would lead me to believe my question is not possible. However the second template I added (which does work) points that at least some visual information from the adorned element lives on in the place holder.
So now my question boils down to a) does this information include the parent of the adorned element and b) how can this be accessed via a binding on a different element?
This ended up being a lot simpler than the path I was trying to go down.
I was doing some reading on the AdornedElementPlaceholder class and came across this entry on MSDN and noticed that the class actually has a property called parent, with that I tried the following binding and it works perfectly:
MaxWidth="{Binding ElementName=adornedElement,
Mode=OneWay,
Path=AdornedElement.Parent.ActualWidth}"
WPF is quite powerful and flexible.
You can bind any property in any XAML tag to any property in any other XAML tag.
For example, you could write a test app that binds the Text property of an input box to the Text property of a label, so as you type something into the text box, the label would change automatically (assuming you use UpdateSourceTrigger=PropertyChanged). This is a direct XAML to XAML binding, with no C# in sight.
Similarly, you could bind the width of your error box to the width of the parent control, whatever that may be.
Google RelativeSource and AncestorType, this is a great link:
http://druss.co/2013/10/wpf-binding-examples/
See if you can grok how the Visual Tree and Logical Tree works in WPF, once you understand that, you will understand more of how binding works.
I'd also recommend using the free tool Snoop to look at the Visual Tree. XAML Spy is excellent, but not free.
Snoop can tell you if there is anything that has a bad binding at runtime (you set the filters up, and it will list all bad bindings).
You can use Snoop to get the full XAML path of your source (the XAML you wrote above), then get the full XAML path of the target (i.e. the ActualWidth of your Grid), then compare them: it may be quickly apparent that one is not the ancestor of the other, as they are on different branches of the visual tree, or that there is some other issue which is preventing a simple walk up the visual tree from working.
If you just want to get something working, as a proof of concept, try naming the target XAML grid using x:Name, and reference it by name instead of AncestorType.
I am using WPF .net 4.5 (c#) and I would like to make a ListBox that contains a series of user controls. (If a listbox is the wrong type of control, please let me know).
I want my listbox to have a copy of the user control as the list items, with different contents within each one.
How do I add user controls to a listbox?
Thanks for your help in advance!
You can set ItemTemplate for the listbox with your usercontrol in it.
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<local:UserControl1/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Thanks
I think you can design a DataTemplate which ha the same UI or Style as this UserControl .
maybe just copy paste can get a DataTemplate as you want,however
<DataTemplate>
<local:UserControl1/>
</DataTemplate>
this king seems very strange for me I dont konw it can work as you want,so I also want to know
the answers。
I'm evaluating the possibilities to view and edit parameters in a C#/WPF/MVVM application. I'm currently looking into some custom controls from WPF Woolkit Extended, Telerik, DevExpress and Syncfusion. I see two options, a PropertyGrid or a DataGrid-like control.
The problem: My parameter content is in a collection and PropertyGrids don't seem to like those, they like to be bound to objects with properties. On the other hand my parameters have different value types and that is something the Data Grids do not favor, there the columns always have the same value editor (e.g. Check box, Date picker etc).
Does anybody know a reliable control that supports binding to a collection and individual value editors per row?
Other requirements are hierarchical data representation, validation and a search function.
DataGrid lets you use a DataGridTemplateColumn, where you can specify a template that will be applied to each cell in that column. This template could contain a UserControl that you have defined, which analyzes its DataContext and shows the appropriate control. (This will be quite a bit of work, though, so if there exist out-of-the-box solutions for this, you should use that instead.)
After a while of investigation I found out that all frameworks have the ability to apply individual cell editors in columns.
This is usually done in the column definition. A grid has a Columns collection. Each column can set a CellTemplateSelector which was the key to my initial problem.
Here is a little snippet for the Telerik grid view, but down to the CellTemplateSelector they all behave the same, as far as I can judge. All the vendor of 3rd party UI libs seems to have copied the behviour of the WPF DataGrid, of course.
<telerik:RadGridView x:Name="radGridView"
AutoGenerateColumns="False">
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn DataMemberBinding="{Binding Name}" Header="Parameter" />
<telerik:GridViewDataColumn DataMemberBinding="{Binding Value}" Header="Value">
<telerik:GridViewDataColumn.CellTemplateSelector>
<telerik:ConditionalDataTemplateSelector>
<telerik:DataTemplateRule Condition="PropertyId < 1">
<DataTemplate>
<TextBox Text="{Binding Value, StringFormat=c}"/>
</DataTemplate>
</telerik:DataTemplateRule>
<telerik:DataTemplateRule Condition="PropertyId > 0">
<DataTemplate>
<CheckBox IsChecked="{Binding Value}" />
</DataTemplate>
</telerik:DataTemplateRule>
</telerik:ConditionalDataTemplateSelector>
</telerik:GridViewDataColumn.CellTemplateSelector>
</telerik:GridViewDataColumn>
</telerik:RadGridView.Columns>
In this example the ItmesSource of the grid is bound to my view model that contains Name, Value and PropertyId properties. Based on the PropertyId a control is selected. The thing I like about the Telerik control is that I don't need code-behind since the ConditionalDataTemplateSelector is available in that framework. Better for MVVM to keep your view clean of code behind, I guess.
UPDATE:
Just received an answer from Syncfusion, they say:
We can load different cell editors in one column. For that we have to Handle dataGrid.Model.QueryCellInfo even and we have to change the CellType based on data. We can't avoid code behind. But this can be achieved using Behaviors.
I want to add a comment to a particular cell of datagridview as the image below. Can it be done?
You can add a RowDetailsTemplate with a TextBlock in it and databind its Text property.
<sdk:DataGrid ItemsSource={Binding Items}>
<!-- Put your columns here -->
<sdk:DataGrid.RowDetailsTemplate>
<DataTemplate>
<TextBlock Text="{Binding Note}" />
</DataTemplate>
</sdk:DataGrid.RowDetailsTemplate>
</sdk:DataGrid>
Hope this helps.
I dount that is possible to add text over multiple cells in a row (in dgv control). Especilly if you want to keep the current text in cells, and add an extra text over these cells (like this comment).
So my answer s no, its not possible. But on the other hand, everything is possisble. You could create a new Label control, and position it on the right place, and add text into it. This means that the label would be actualy placed over the dgv control. This is one of thr idea.
I think if you wanna do something like you want to, you would have to do something extra (something unusual).
After quite some time I discovered the exact solution to prove that Matt is right.
Following is a beautiful link to do the same.
http://msdn.microsoft.com/en-us/library/85kxk29c.aspx