Unable to copy text to clipboard while bound - wpf

I am having a textblock element in WPF application that is bound to a combobox and I want the textbox text value to be copied to the clipboard when a button is pressed but i am unable to get the text value in the code behind as i am unable to use the textbox name itself to refer to its properties. This is a follow up to my previous question over here
Getting XML element from a Combobox item
the code is over there so donot want to extend the question these are the simple two lines of code
<TextBox Grid.Column="1"
Text="{Binding SelectedItem.Value, ElementName=QueryChooser}"
Grid.ColumnSpan="2" Grid.Row="1" Height="200" HorizontalAlignment="Left"
Name="textBlock1" VerticalAlignment="Top" Width="481" />

Firstly, I would recommend looking into the MVVM design pattern if you are serious about doing any WPF development. If you are using MVVM, then use an MVVM framework. It will make your life considerably easier.
Secondly, you need some kind of mechanism for invoking verbs on your data context (a view model in MVVM). WPF provides commanding, and MVVM frameworks provide other techniques and variations.
Once you have this mechanism, then you have the query text in your SelectedQuery property, so you can copy SelectedQuery.Value (a string) to the clipboard.

write CopyingCellClipboardContent event in your datagridTemplateColumn in xaml.
In code behind in this event write this,
if (dataGrid1.CurrentCell != null && dataGrid1.CurrentCell.Column == e.Column)
{ dataGrid1.SelectionUnit=Microsoft.Windows.Controls.DataGridSelectionUnit.Cell;
e.Content = ((System.Data.DataRowView)(dataGrid1.CurrentCell.Item)).Row.ItemArray[4].ToString();
}
else
e.Content = true;
Thanks..

Related

Call controls inside view(xaml file) in viewmodel

I want to call controls inside view like button and item template inside viewmodel. Please tell how can I do that. My view contains following
<ItemsControl Name="cDetails"
Width="395"
ItemTemplate="{DynamicResource Test}"
ItemsSource="{Binding ViewModels}"
Visibility="{Binding IsLoaded,
Converter={StaticResource visibilityConverter}}">
<Button Name="btnComplete"
Grid.Column="1"
HorizontalAlignment="Center"
Command="{Binding AuditCommand}"
CommandParameter="1">
Complete
</Button>
Please tell how can I call these items in my viewmodel using vb.net.
Thanks
Accessing your view components from inside your viewmodel is not the way to do things in MVVM. Because it is specifically not designed to work this way, you will have to go out of your way to make it work. You should probably investigate how to accomplish your goals using MVVM properly, or forego using MVVM at all and do the work in your code-behind.
Since you have not described what your goal is, it is hard to provide specific recommendations. In general when using MVVM, you manipulate things in your viewmodel and set properties. Your view binds to these properties so that it updates appropriately as they are being set. Your viewmodel does not directly manipulate the views themselves, only the viewmodel properties that they are bound to.
For example, let's say you are updating the text on a TextBlock. You could do something like this in xaml:
<TextBlock Text="{Binding SomeText}" />
Then, your viewmodel (which should implement the INotifyPropertyChanged interface) defines this property and sets it as desired.
public string SomeText
{
get { return _someText; }
set
{
if (_someText != value)
{
_someText = value;
NotifyPropertyChanged("SomeText");
}
}
}
private string _someText;
...
// At any time, you can set the property, and the
// binding will update the text in the control for you.
SomeText = "Some text";
If you absolutely need to manipulate your views from code (or if you are not using MVVM), the appropriate place for that sort of code is the "xaml.cs" file next to your view (the code-behind). You can assign a name to anything in your xaml using syntax like <TextBlock x:Name="SomeTextBlock" /> and then access it from the code-behind as a member variable with the same name. For example, you could do SomeTextBlock.Text = "Some text". However, this is not usually necessary for the vast majority of use cases if you are using MVVM.
You shouldn't try to access controls directly from the ViewModel. The ViewModel must not know about the View implementation.
Instead, in WPF we connect View and ViewModel through Bindings. Bindings connect Properties of controls in the View, with Properties in the ViewModel.
Commands are a special type of Property that can be bound as actions for controls like Button.
In your example, you would need to have these properties in your ViewModel:
A collection named ViewModels
A boolean named IsLoaded
And an ICommand named AuditCommand
By managing those properties, you should be able to control what's shown in your View and its behavior.
If you need more control, create more Bindings to other properties, or create some events in your ViewModel and manage them from your View's code-behind.

How does WPF handle binding to the property of a null object?

I have a listBox using an itemTemplate that contains the following line:
<Image Source="{Binding MyProperty.PossiblyNullObject.UrlProperty}"/>
Bound to this listBox is a model view collection that loads components of the items in the collection on a separate thread. The 'PossiblyNullObject' may not be set to a value when the xaml code is first rendered by the composition engine.
How does WPF handle this? Does it use a default value(no image source so no image) and continue on? Does it wait? Does it automatically detect when the value is initialized and rerenders with the new source? How does it not throw object null exceptions in the same way it would if I called 'MyProperty.PossiblyNullObject.UrlProperty' programmatically? How can I reproduce this functionality in my own code when I try to call it?
Thanks for any suggestions. I am embarrassingly new to WPF and I'm trying to tackle a problem out of my depth. The image load is a perf problem so I found a solution to load, decode, then freeze the image source on a background thread so it wouldn't lock up the UI. Unfortunately, I ran across this null exception problem when I tried replacing the image source binding with my solution that calls the same property. WPF somehow handles the possible null objects and I'd like to do it the same way to keep things clean.
In BindingBase have two properties: TargetNullValue and FallbackValue.
TargetNullValue returns your value when the value of the source is null.
FallbackValue returns your value when the binding is unable to return a value.
Example of using:
<!-- xmlns:sys="clr-namespace:System;assembly=mscorlib" -->
<Window.Resources>
<!-- Test data -->
<local:TestDataForImage x:Key="MyTestData" />
<!-- Image for FallbackValue -->
<sys:String x:Key="ErrorImage">pack://application:,,,/NotFound.png</sys:String>
<!-- Image for NULL value -->
<sys:String x:Key="NullImage">pack://application:,,,/NullImage.png</sys:String>
</Window.Resources>
<Grid DataContext="{StaticResource MyTestData}">
<Image Name="ImageNull"
Width="100"
Height="100"
Source="{Binding Path=NullString, TargetNullValue={StaticResource NullImage}}" />
<Image Name="ImageNotFound"
Width="100"
Height="100"
Source="{Binding Path=NotFoundString, FallbackValue={StaticResource ErrorImage}}" />
</Grid>
See this links, for more information:
BindingBase.TargetNullValue Property
BindingBase.FallbackValue Property
Note: The upvoted and accepted answer does not answer the question; it explains how you can get {Binding A} to work if A is null, which is trivial to handle anyway, but it does not explain what happens and how to handle the much more interesting case of {Binding A.B} when A is null, and that is specifically what the question is asking. What follows is the answer to the question as stated.
WPF generally handles the case where A is null when you use A.B in a binding; I have not tried specifically with <Image Source>, but I have tried with <DataGrid ItemsSource> and with <Button Command>.
When WPF handles these cases, what I have observed happening is that there is no error or warning in the output window, and the application malfunctions a bit, but it does not crash:
In the case of <DataGrid ItemsSource>, the DataGrid appears empty.
In the case of a <Button Command>, the button is clickable, but when you click it nothing happens.
In the case of <Image Source> I would expect that no image will appear.
(Note that all these are cases of silent failure, so whoever decided that WPF should behave this way should be shot by firing squad at the central square with great celebrations and live music and big giveaways.)
The way we generally handle these cases depends on the nature of the element at hand.
For images, if an empty image is acceptable, then you do not need to do anything. If some image must be shown despite the property being null, then the accepted answer probably provides a solution.
For grids, not showing anything when the property is null is probably the desired behavior.
For buttons, the solution is to use an additional binding to the IsEnabled property of the button.
So, for example:
<Button Command="{Binding A.B}" IsEnabled="{Binding HasA}"/>
Where HasA is defined in the viewmodel as follows:
bool HasA => A != null;

WPF TreeView question

Is it possible to store some data in every item of a TreeView control? I mean, something useful (e.g. a string) besides the header text?
Thanks.
Yes, WPF is "lookless", so your actual data can be anything you want it to be, and a TreeView is just a Template used to display the data to the user in a pre-determined way.
You can overwrite any part of that Template to be whatever you want, and/or have it bind to your data however you want.
Edit
I'm no expert on using the TreeView, but if you had a DataContext of List<Folder>, and each Folder object had a Name and a FullPath property, your TreeView could look something like this:
<TreeView ItemsSource="{Binding MyFolderList}">
<TreeView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"
ToolTip="{Binding FullPath}" />
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
If you haven't already, I'd highly recommend looking into the MVVM design pattern when working with WPF. Basically your application is your classes (ViewModels), and the Controls/XAML (Views) are just a pretty layer that sits on top of your classes to make them user-friendly.
This is an important concept when switching from a WinForms TreeView to a WPF TreeView
It depends on what you mean by store data...
If you're just talking UI customization Rachel's answer above works.
If you're talking about storing arbitrary object values, such as information about the TreeViewItem, or maybe a relation between two items, you can use the Tag property of TreeViewItem. For example, I had to write a mapping UI where two trees linked together where each TreeViewItem from the first tree, could connect to 1 TreeViewItems of the second tree. I used the Tag property of the first TreeViewItem to store the connecting TreeViewItem.

How do you navigate a complex Visual Tree in order to re-bind an existing element?

In the above image, child is a ContentPresenter. Its Content is a ViewModel. However, its ContentTemplate is null.
In my XAML, I have a TabControl with the following structure:
<local:SuperTabControlEx DataContext="{Binding WorkSpaceListViewModel}"
x:Name="superTabControl1" CloseButtonVisibility="Visible" TabStyle="OneNote2007" ClipToBounds="False" ContentInnerBorderBrush="Red" FontSize="24" >
<local:SuperTabControlEx.ItemsSource>
<Binding Path="WorkSpaceViewModels" />
</local:SuperTabControlEx.ItemsSource>
<TabControl.Template>
<ControlTemplate
TargetType="TabControl">
<DockPanel>
<TabPanel
DockPanel.Dock="Top"
IsItemsHost="True" />
<Grid
DockPanel.Dock="Bottom"
x:Name="PART_ItemsHolder" />
</DockPanel>
<!-- no content presenter -->
</ControlTemplate>
</TabControl.Template>
<TabControl.Resources>
<DataTemplate DataType="{x:Type vm:WorkSpaceViewModel}">
....
WorkSpaceViewModels is an ObservableCollection of WorkSpaceViewModel. This code uses the code and technique from Keeping the WPF Tab Control from destroying its children.
The correct DataTemplate - shown above in the TabControl.Resource - appears to be rendering my ViewModel for two Tabs.
However, my basic question is, how is my view getting hooked up to my WorkSpaceViewModel, yet, the ContentTemplate on the ContentPresenter is null? My requirement is to access a visual component from the ViewModel because a setting for the view is becoming unbound from its property in the ViewModel upon certain user actions, and I need to rebind it.
The DataTemplate is "implicitly" defined. The ContentPresenter will first use it's ContentTemplate/Selector, if any is defined. If not, then it will search for a DataTemplate resource without an explicit x:Key and whose DataType matches the type of it's Content.
This is discussed here and here.
The View Model shouldn't really know about it's associated View. It sounds like there is something wrong with your Bindings, as in general you should not have to "rebind" them. Either way, an attached behavior would be a good way to accomplish that.
I think the full answer to this question entails DrWPF's full series ItemsControl: A to Z. However, I believe the gist lies in where the visual elements get stored when a DataTemplate is "inflated" to display the data item it has been linked to by the framework.
In the section Introduction to Control Templates of "ItemsControl: 'L' is for Lookless", DrWPF explains that "We’ve already learned that a DataTemplate is used to declare the visual representation of a data item that appears within an application’s logical tree. In ‘P’ is for Panel, we learned that an ItemsPanelTemplate is used to declare the items host used within an ItemsControl."
For my issue, I still have not successfully navigated the visual tree in order to get a reference to my splitter item. This is my best attempt so far:
// w1 is a Window
SuperTabControlEx stc = w1.FindName("superTabControl1") as SuperTabControlEx;
//SuperTabItem sti = (SuperTabItem)(stc.ItemContainerGenerator.ContainerFromItem(stc.Items.CurrentItem));
ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(stc);
//ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(sti);
DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
The above code is an attempt to implement the techniques shown on the msdn web site. However, when I apply it to my code, everything looks good, except myDataTemplate comes back null. As you can see, I attempted the same technique on SuperTabControlEx and SuperTabItem, derived from TabControl and TabItem, respectively. As described in my original post, and evident in the XAML snippet, the SuperTabControlEx also implements code from Keeping the WPF Tab Control from destroying its children.
At this point, perhaps more than anything else, I think this is an exercise in navigating the Visual Tree. I am going to modify the title of the question to reflect my new conceptions of the issue.

How to bind StackPanel Children from a ViewModel?

New to Silverlight. I'm working on a chat application where new chat messages are added to the bottom of a list. I had a working version that used as StackPanel inside a ScrollViewer and then in some code behind used StackPanel.Children.Add().
I'm trying to convert this to a View-ViewModel approach, and I can't figure out how to bind the Children of the StackPanel to any collection property. I've tried this:
<ScrollViewer Name="scrollMessages" Grid.Row="2" Margin="0,0,0,0" VerticalScrollBarVisibility="Visible">
<StackPanel x:Name="pnlMessages" Orientation="Vertical" Children="{Binding Path=ExampleTBs}" />
</ScrollViewer>
where ExampleTBs is a collection of TextBlocks created in code. This fails XAML parsing, the Children property isn't bindable in this way.
Is the approach of binding to the StackPanel itself fixable? Should I be using a different container type? I saw another question where the guy created the entire StackPanel in code and then used a ContentPresenter...
Bottom line, I'd like to find a way to databind my view to a viewmodel using something like a StackPanel as a container where successive items will be added to the container over time. Best approach?
Use a ListBox (or any other ItemsControl) and bind the ItemsSource property to an ObservableCollection in your ViewModel.
Do you need to use a StackPanel? If you use an ItemsControl instead, this still presents each chat message in a vertical list, and also allows for binding of the data.

Resources