I was trying to get the text that I wrote in a DataGrid cell after editing it, so I put a breakpoint in the function CellEditEnding and looked at the EventArgs and noticed that it contains the property "Text", so I wouldn't have to do the usual XAML binding hacks to get it.
However, I quickly noticed that it will not let me access it.
After taking a look at the FrameworkElement class, I can confirm that there is no Text property, so what is going on, why can't I acces the property?
why can't I acces the property?
Because a FrameworkElement indeed has no Text property.
TextBox, which derives from FrameworkElement, has a Text property though so you could cast the EditingElement to a TextBox and then access the property:
string text = (e.EditingElement as TextBox)?.Text;
Visual Studio displays the properties of the actual object in memory.
It's a bad idea to use the UI as a data store and try and directly work with it.
You should bind an observablecollection of t to the itemssource of your datagrid and work with each instance of t.
That will be far easier to work with.
As to why are some properties inaccessible?
It's because those properties aren't where you think they are. The DatagridCell has a series of things nested within it.
DataGridCell > Border > ContentPresenter > TextBlock
Download snoop https://github.com/snoopwpf/snoopwpf or install using chocolatey / your preferred method.
Run snoop.
Run your app.
Drag the right gunsight thing over you window.
A window should open up with two panels. Controls and properties.
Mouse over a datagrid cell.
press shift+ctrl and you should see the element under the mouse selected in the ui tree.
A datagrid is pretty complicated and there are multiple things in each row.
See that textblock there?
That's the thing has a text property.
Or at least that's the thing when you're not in edit mode.
Switch to edit mode and I have a TextBoxView.
So one complication is, which are you working with at a given time?
Related
I have a WPF project with a DataGrid in my window and, initially, I just set its ItemsSource to a collection of objects, and the grid auto-generated columns, based on their properties. In that stage when starting the application I, as the user, could click a cell (in the user interface) and it would allow me to select/drag-select part of the text in that cell.
Now I disabled the auto-generation of columns and defined custom columns, binding them to select properties of said objects. And now clicking a cell just selects the entire cell and its entire contents. I've looked at all DataGrid and DataGridCell properties but don't see anything which would obviously alter this behaviour.
How can I set a manually defined DataGridTextColumn in the XAML to have the text content of its cells be partially selectable, instead of only being able to select the entire cell content?
The DataGridTextColumn is behaving the same whether it is autogenerated or not. Maybe you are setting IsReadOnly = True. That could be one reason for it to behave like you are describing. Otherwise, you have to provide us with code and data, that is showing your case.
I want to thank RolandJS, his answer made me realise I probably could inspect WPF controls' properties at debug time and that led me to the Live Visual Tree, seeing all properties are the same, which led me to the binding, which was mode = one way.
So, basically, the text in DataGrid cells can only be partially selected/drag selected if the binding is in a mode that allows changing the source, because that is what you are potentially doing.
I am not using anything other than a simple WPF application project in visual studio. I've implemented an mvvm application.
I want to display a list of content changes made by a user. I have a main window view model and it currently just builds a strings with changes. I have objects that I can reuse to display their properties (the content).
Currently, I use a MessageBoxResult to show a really long string with the changes. This is a terrible design (I know), but I couldn't really find an answer to what class a regular wpf project has that would allow me to achieve what I want.
I know there is a popup class I can use. In practice, which is better-- another view model for the dialog, or a popup?
Can anyone provide a simple example of one of the two approaches?
Thank you in advance for your response.
What I've done in the past is have a simple Border control, and inside of a TextBlock and whatever Button controls I need. I bind the TextBlock.Text to a public string property named "MessageBoxMessage" which calls OnPropertyChanged(). I bind the Command of each Button to a separate public ICommand which specifies what action to take in the view model when the button is clicked. I then bind the visibility of the Border control - which contains all of the other controls I mentioned - to a Visibility property.
When I want to show a dialog, I set the MessageBoxMessage to the message I want to show, makes sure the commands are set properly, and then set the Visibility on the Border to Visibility.Visible. This shows the box (border), message, and buttons.
You can even implement a semi-transparent rectangle underneath the border (over the rest of the form) that you set to visible at the same time. This will give you the nice "form dimmed" effect and also block the normal form controls from being clicked. A general note - for this to work, these controls need to be at the very bottom of your XAML as the z-index among controls at the same level is inferred from their placement in the XAML - lower in the code is top level on the form.
Let me know if you have any questions about implementing this if it sounds like what you are looking for.
This is probably very simple to do, but I'm having a brain fart (being sleep deprived will do that to you).
I've got a WPF User Control and I want to expose a property (as read only) of one of its child controls to the outside world so I can bind to it.
Whats the best way?
I think I should expand on this, as it may be more fiddly than I gave an impression of. I've got a grid with a column in it of width "*". When its contents have been loaded I want to be able to get the ActualWidth of the column and pass that out of the usercontrol as a read only property (so I can bind another control to the same value and have it match the size).
I'm not sure how to set up a dependency property to do this properly.
I have a weird problem, and I don't know if this is the default behaviour of .Net DataGridView inside a GroupBox/TabControl.
I've created a new WinForm project from scratch, and created a GroupBox(changed the text style). Like this:
alt text http://www.freeimagehosting.net/uploads/65f5f2762d.png
Then, I've created a simple DataGridView, no font style at all, like this:
alt text http://www.freeimagehosting.net/uploads/09f55f951a.png
Then, in design mode, I dragged the DataGridView inside the GroupBox, and this sort of magic just happened:
alt text http://www.freeimagehosting.net/uploads/d0334132f0.png
My question is, can I disable this behaviour? Cause if I chage the DataGridView style outside the GroupBox and then drag it into, lost all the style.
Just for the record, this form has NO CODE at all.
Thanks in advance.
Try putting a panel in the group box, then setting the font property of the panel. This way the DataGridView will inherit the properties of the panel. Much easier than setting every font property of the DataGridView.
What you are experiencing is known as Ambient Properties. In short it is a mechanism where a control will "inherit" some property values from its parent, if the properties are not explicitly assigned to. I don't know of a way to prevent the behavior, other than assigning the wished values to the properties.
I have a class ToolTipProvider
which has a method
string GetToolTip(UIElement element)
which will return a specific tooltip for the UIElement specified, based on various factors including properties of the UIElement itself and also looking up into documentation which can be changed dynamically. It will also probably run in a thread so when the form first fires up the tooltips will be something like the visual studio 'Document cache is still being constructed', then populated in the background.
I want to allow this to be used in any wpf form with the minimum effort for the developer. Essentially I want to insert an ObjectDataProvider resource into the Window.Resources to wrap my ToolTipProvider object, then I think I need to create a tooltip (called e.g. MyToolTipProvider) in the resources which references that ObjectDataProvider, then on any element which requires this tooltip functionality it would just be a case of ToolTip="{StaticResource MyToolTipProvider}"
however I can't work out a) how to bind the actual elemnt itself to the MethodParameters of the objectdataprovider, or b) how to force it to call the method each time the tooltip is opened.
Any ideas/pointers on the general pattern I need? Not looking for complete solution, just any ideas from those more experienced
Create a new user control which functions as a tool-tip view factory.
Use your control as the tool-tip, passing any data you need for the factory to your control using binding (e.g. the data, the containing control, ...)
<AnyControl>
<AnyControl.ToolTip>
<YourToolTipControl Content="{Binding}" />
</AnyControl.ToolTip>
</AnyControl>
Not calling myself an expert, but I'd probably attempt such a feature with an attached property. This would be attachable to any element in your UI and you can specify an event handler that gets access to the object to which the property is being attached as well as the value passed to the attached property. You can keep a reference to the element to which your attached property was attached and you would then be able to change the ToolTip whenever you want.