I'm trying to create a common converter that will take in a string from a resource resx file (the app has to be localizable) as a parameter.
<TextBlock
ToolTipService.ToolTip="{Binding IsInUse, ConverterParameter={Binding Path=WhereUsedIndicatorTooltips, Source={StaticResource resource}}, Converter={StaticResource whereUsedIndicatorTooltipConverter}}" />
Where resource is declared at the top of this page in XAML as:
<UserControl.Resources>
<resources:myResource x:Key="resource" />
</UserControl.Resources>
At runtime I get this exception:
System.Windows.Markup.XamlParseException:
Provide value on
'System.Windows.Data.Binding' threw an
exception. [Line: 47 Position: 42]
---> System.InvalidOperationException: Operation is not valid due to the
current state of the object.....
I'm aware from this StackOverflow question that the ConverterParameter is not bindable and is not a DependencyObject. Is there a workaround to this problem, besides putting the text in the XAML?
I found a solution from Brandon Truong. This works very well.
I put my FrameworkElement with DependencyProperty converter in:
<UserControl.Resources>
<utilConverters:myTooltipConverter x:Key="myTooltipConverter" Tooltips="{Binding Path=tooltips, Source={StaticResource resource}}" />
</UserControl.Resources>
I got same error here ,
**
ElementName=RadCalendarMonths,Path=SelectedDate,StringFormat='MMMM
yyyy',ConverterCulture={Binding Path=CurrentCultureInfo,
Source={StaticResource ResourceWrapper}}}"/>
I used Converter Culture property Binded! Opps! I can't do that because the property ConverterCulture is not a DependencyProperty. If a property is not instance of DependencyProperty you cant use binding on it.
If you look at Property(F4) Pane on VS2010 you can see that some properties support Binding some properties does not! Some properties not seen there because some properties are read only as u know.
So using resource is a logical way to solve it.
Related
I've got a View with a CefSharp.WPF component embedded in it, and I need to be notified when it's initialized, and when it's loading etc.
Because there are no conventions for this built into Caliburn.Micro I've used cal:Message.Attach like so:
<cefsharp:ChromiumWebBrowser Name="Browser" Visibility="Visible" TabIndex="3"
WebBrowser="{Binding WebBrowser, Mode=OneWayToSource}"
Address="http://localhost:8080/"
Title="{Binding Title, Mode=OneWayToSource}"
cal:Message.Attach="[Event FrameLoadStart] = [Action OnLoading()]"/>
In my View Model I then have a simple action:
public void OnLoading()
{
System.Windows.MessageBox.Show("Loading");
}
However, when I start the application it almost immediately throws a System.InvalidOperationException because it's trying to access something on another thread.
System.InvalidOperationException was unhandled
Message: An unhandled exception of type 'System.InvalidOperationException' occurred in WindowsBase.dll
Additional information: The calling thread cannot access this object because a different thread owns it.
Is there any way around this - to make sure the action is called on the proper thread (or vice versa), or is there a better way to achieve the same effect?
I am trying to implement design time Unity configuration (e.g.: using app.config). I am struggling with the very example of how to use the tag the "configuring instances" section.
Their sample of run-time configuration is:
EmailService myEmailService = new EmailService();
myContainer.RegisterInstance<IMyService>(myEmailService);
but no equivalent design-time configuration given. If I do:
<container>
<instance type="IMyService" value="EmailService" />
</container>
I will naturally get a "TypeConverter cannot convert from System.String" exception. Am I supposed to create some sort of type converter merely so that I could declare an instance? Is there an easier way?
I'm trying to dynamically switch the DataContext for my application when the selection of a Pivot item changes. Everything works as I want it to, however I keep getting errors in the debugger output window about data sources not being found from the ListBoxes present inside the PivotItems that are not the currently selected PivotItem.
For instance, let's say I have 2 PivotItems - PivotItem1 and PivotItem2 - each displaying one ListBox each - ListBox1 and ListBox2. Now, when PivotItem1 is active and displaying ListBox1, ListBox2 complains about its data source not being found, which is correct because the current DataContext does not contain the collection it is bound to. This is the error (I've added extra line breaks):
System.Windows.Data Error: BindingExpression path error:
'Entries' property not found on 'MyApp.ViewModels.CategoriesView'
'MyApp.ViewModels.CategoriesView' (HashCode=79283607).
BindingExpression: Path='Entries'
DataItem='MyApp.ViewModels.CategoriesView'
(HashCode=79283607); target element is
'System.Windows.Controls.ListBox' (Name='ListBox2');
target property is 'ItemsSource' (type 'System.Collections.IEnumerable')..
Similarly, when PivotItem2 is active, ListBox1 throws an error. I'm updating the DataContext within the LoadingPivotItem event of the Pivot, I've also tried doing this within the LoadedPivotItem event but get the same error.
Both collections implement INotifyPropertyChanged, and as I mentioned at the beginning, everything works, despite the error. I'd like to suppress the error somehow.
Here's the XAML for one the ListBoxes:
<ListBox x:Name="ListBox1"
Margin="0,0,-12,0"
ItemsSource="{Binding Categories}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17"
Width="432">
<TextBlock Text="{Binding CategoryName}"
TextWrapping="Wrap"
Margin="12,0,0,0"
Style="{StaticResource PhoneTextExtraLargeStyle}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The other is identical, except "Categories" is replaced by "Entries" and "CategoryName" by "EntryName".
Thanks in advance for your help.
While the action you're performing doesn't cause any errors in your application there will be an impact on the device as a whole while the Silverlight framework handles the binding errors.
Rather than having two different data models and changing them, why not have a single model which contains the "Categories" and "Entries" models but just set the one you're not displaying to be an empty collection (or whatever as appropriate). This would allow the bindings to still work but would prevent population of the list boxes you're not displaying.
I've got a datagrid column as below:
<toolkit:DataGridTemplateColumn>
<toolkit:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=LabelName}" Background="{Binding Path=Color}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem x:Name="Assign" Header="Assign"
mvvm:CommandBehavior.Event="Click"
mvvm:CommandBehavior.Command="{Binding Path=DataContext.EditLabelCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}, AncestorLevel='1'}}"
mvvm:CommandBehavior.CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}, Path=DataContext}"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</toolkit:DataGridTemplateColumn.CellTemplate>
I'm trying to get to the DataContext's EditLabelCommand, but I cannot find the binding source. What should I do to access my DataContext's commands?
DataContext changes as you move down the visual tree when you either a) bind DataContext to something else, or b) use something like an items control (or in your case a grid), which repeats your data template once per item in a collection, setting the data context for each item.
In your example, your menu item has the same DataContext as your TextBlock. This will be the object bound to each row of your data grid.
Based on your code, I think you have one EditLabelCommand available in the DataContext set for your entire UserControl. This is likely the parent of the collection you are binding to the grid. (Please correct me if any of these assumptions are wrong.)
If this is the case, there are several things you can do:
You can continue to use relative binding. This is complex and error
prone, as you have seen, and does not lead to good reuse of your data
templates or other XAML. I recommend you avoid this technique.
A simpler way to keep the command in the overall datacontext is to use
a CommandReference from the WPF Model-View-ViewModel Toolkit. This
allows you to reference the command as a resource and use resource binding to
access it. Like this:
<UserControl.Resources>
<mvvmToolkit:CommandReference x:Key="EditLabelCommandReference" Command="{Binding EditLabelCommand}" />
</UserControl.Resources>
<!-- Your command binding then looks much simpler -->
mvvm:CommandBehavior.Command="{StaticResource EditLabelCommandReference}"
Another (probably better) technique is to refactor to use the MVVM pattern for each row. This way, you would use a simple ViewModel per row of your grid. This allows each row to maintain its own state. Because you can move the Command implementation into this ViewModel, you have a command per row and no need to pass an argument. This makes it possible to edit more than one row's label at a time. (If this a requirement.)
I have a generic Repository<T> class I want to use with an ObjectDataSource. Repository<T> lives in a separate project called DataAccess. According to this post from the MS newsgroups (relevant part copied below):
Internally, the ObjectDataSource is calling Type.GetType(string) to get the
type, so we need to follow the guideline documented in Type.GetType on how
to get type using generics. You can refer to MSDN Library on Type.GetType:
http://msdn2.microsoft.com/en-us/library/w3f99sx1.aspx
From the document, you will learn that you need to use backtick (`) to
denotes the type name which is using generics.
Also, here we must specify the assembly name in the type name string.
So, for your question, the answer is to use type name like follows:
TypeName="TestObjectDataSourceAssembly.MyDataHandler`1[System.String],TestObjectDataSourceAssembly"
Okay, makes sense. When I try it, however, the page throws an exception:
<asp:ObjectDataSource ID="MyDataSource" TypeName="MyProject.Repository`1[MyProject.MessageCategory],DataAccess" />
[InvalidOperationException: The type specified in the TypeName property of ObjectDataSource 'MyDataSource' could not be found.]
The curious thing is that this only happens when I'm viewing the page. When I open the "Configure Data Source" dialog from the VS2008 designer, it properly shows me the methods on my generic Repository class. Passing the TypeName string to Type.GetType() while debugging also returns a valid type. So what gives?
Do something like this.
Type type = typeof(Repository<MessageCategory);
string assemblyQualifiedName = type.AssemblyQualifiedName;
get the value of assemblyQualifiedName and paste it into the TypeName field. Note that Type.GetType(string), the value passed in must be
The assembly-qualified name of the type to get. See AssemblyQualifiedName. If the type is in the currently executing assembly or in Mscorlib.dll, it is sufficient to supply the type name qualified by its namespace.
So, it may work by passing in that string in your code, because that class is in the currently executing assembly (where you are calling it), where as the ObjectDataSource is not.
Most likely the type you are looking for is
MyProject.Repository`1[MyProject.MessageCategory, DataAccess, Version=1.0.0.0, Culture=neutral, PublicKey=null], DataAccess, Version=1.0.0.0, Culture=neutral, PublicKey=null
I know this is an old post but I have recently had this problem myself. Another solution would be to replace the inheritance with object composition, e.g.
[DataObject]
public class DataAccessObject {
private Repository<MessageCategory> _repository;
// ctor omitted for clarity
// ...
[DataObjectMethod(DataObjectMethodType.Select)]
public MessageCategory Get(int key) {
return _repository.Get(key);
}
}
This way the ObjectDataSource doesn't know about the repository because its hidden within the class. I have a class library in my facade layer that is a perfectly reasonable place to put this code in the project I am working on.
In addition, if you are using Resharper and interfaces, its possible to get Resharper to do the refactoring using Resharpers "Implement using field" function.
Darren,
Many, many thanks for your post. I've been fighting with this all day. Strangely, in my case, I need to double the square brackets, e.g. for your piece of code:
MyProject.Repository`1[[MyProject.MessageCategory, DataAccess, Version=1.0.0.0, Culture=neutral, PublicKey=null]], DataAccess, Version=1.0.0.0, Culture=neutral, PublicKey=null
Roger