|
Hi,
Do you know how to play a DVD in WPF platform?
The MediaElement doesn't support this format, and i try to use the VLC Component.
The MediaToolkit that many people suggest me doesn't work.
Thanks for your attention,
Regards,
Alessio.
|
|
|
|
|
I have a sneaky feeling this is going to be one of those DRM issues. I'm pretty sure the reason for the media player control not being able to read DVD formats is the encoding and that is due to DRM copyrights.
I could be wrong but I feel correct about this.
|
|
|
|
|
I have three UI elements on my View that are Bound to a Property in my ViewModel:
...
xmlns:myViewModel="clr-namespace:....ThisViewModel"
<TextBlock Text="{Binding Path=LengthProperty.Name}" .../>
<TextBlock Text="{Binding Path=LengthProperty.Value}" .../>
<TextBlock Text="{Binding Path=LengthProperty.UOM}" .../>
This works as expected and shows no data when the LengthProperty is Nothing.
I want to modify this so that when the LengthProperty is Nothing, the view displays data from an alternative CavityProperty property in the ViewModel.
Can this be done in xaml? or should I code it in the ViewModel?
Any pointers are most appreciated.
I don't speak Idiot - please talk slowly and clearly
'This space for rent'
Driven to the arms of Heineken by the wife
|
|
|
|
|
Sounds like a job for a multi value converter.
|
|
|
|
|
I think you are right. It is the implementation I am struggling with. I assume the Converter lives with the ViewModel, however, accesing it in the view is proving probematic...
...
<TextBock.Text>
<MultiBinding Converter="{ ??? }">
<Binding Path="lenProp"/>
<Binding Path="cavProp"/>
</MultiBimding>
</TextBlock.Text>
How do I access the Converter (<MultiBinding Converter="{ ??? }"/> ) ?
\_{"/)_/
I don't speak Idiot - please talk slowly and clearly
'This space for rent'
Driven to the arms of Heineken by the wife
|
|
|
|
|
The converter doesn't live in your VM. It's a completely separate standalone class.
namespace TheSameNameSpaceAsYourVMForConvience
{
public class MyMultiValueConverter : IMultiValueConverter
{
}
}
then in your XAML, in your resources section (assuming local is pointing to your namespace):
<Window.Resources>
<local:MyMultiValueConverter x:Key="MyMultiValueConverter" />
</Window.Resources>
to access it:
<MultiBinding Converter="{StaticResource MyMultiValueConverter}">
</MultiBinding>
The logic in your convert function is going to be something like:
if ((string)values[0] != null && (string)values[0] != "")
return values[0];
return values[1];
|
|
|
|
|
I have solved this (temporarily) in the ViewModel by creating a Public MultiProperty() As ProdPropertyItem which calls a Function ValueConverter() As ProdPropertyItem that resolves the correct property.
I call the function in the Property Setter when a new Parent Item is seleted and the correct values are displayed in the UI . However, this enables OneWay binding only.
I will re-investigate the MulitiBinding Converter stuff when I get more time.
(Infact I have tried pretty similar code to what you have posted, although I am not yet seeing the fields of the converted property)
I don't speak Idiot - please talk slowly and clearly
'This space for rent'
Driven to the arms of Heineken by the wife
|
|
|
|
|
Alternatively set up 2 sections, 1 binding to the Length and the other binding to the Cavity, another 2 properties determining the visibility of the 2 sections based on the content.
Not sure if this is the most appropriate solution but it does seem logical and possibly simpler.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Thanks Mycroft, this is what I have basically done by exposing a Single "SharedProperty" Item and wiring up the visibility in the ViewModel.
I still feel that I should be able to detrmine the appropriate Object in xaml and then display the(3) public properties in the UI without creating extra Public Properties in the ViewModel.
(Disclaimer: I am a novice to this and have only just recently had my MVVM + WPF LightBulb Moment[^] so I may have this a bit screwed!)
I don't speak Idiot - please talk slowly and clearly
'This space for rent'
Driven to the arms of Heineken by the wife
|
|
|
|
|
Andy_L_J wrote: I still feel that I should be able to detrmine the appropriate Object in xaml and then display the(3) public properties in the UI
I wonder why? While the converter may be the technically correct method I feel the VM should do whatever it needs to service the views requirements. I often create a bunch bool(s) in the VM to manage the state of the view based on the data content.
I also consider the use of a converter to be more obscure from a support point of view which for me is a large consideration.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Mycroft Holmes wrote: I still feel that I should ...
Thats it, it's just a "feeling", due no doubt to my inexperience with this pattern. I have been coding (3/4 Tier) Windows Apps using CSLA and have found the transition a little difficult at first. I am also digging into Entity Framework and Linq to Entities so am having a great time of it.
From my point of view, it was very easy to accomplish my goal in the VM. And as for two-way binding, since I dont intend updating the Model from this view there is no issue. There will be a separate view to performm the New/Edit operations.
I don't speak Idiot - please talk slowly and clearly
'This space for rent'
Driven to the arms of Heineken by the wife
|
|
|
|
|
I have to admit, I cheat with the multiple view/VM structure. I often service 2 different views from the same VM. The list is fairly simple, 1 observable collection with a selected item. The dialog (Add/Edit) is also serviced by the same view using the IEditable from the underlying model to determine the state. A bunch of standard CRUD methods and the VM is done for simple operations. Takes about 15 minutes for a table/model/WCF DAL/VM/2 Views for a simple operation.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Mycroft Holmes wrote: I often create a bunch bool(s) in the VM to manage the state of the view based
on the data content.
Which is often extremely silly, unnecessary, unmaintainable and not the right way to go.
1) If you write a generic converter, you can often re-use it, not only for multiple properties, but multiple views.
By generic converter, no, I don't mean one that converts empty strings to "(Empty)" and another one that converts falses to "Off" for example. I mean, one that say could convert any object & value to any other object & value.
A few EXCELLENT examples of true GENERIC converters: a map converter and a math converter
Too often I see BoolToVisibilityConverter and InverseBoolToVisibilityConverter, etc. when you could have done both and then some with the generic MapConverter.
2) Other then the generic converters, the other option is of course triggers. I'm betting I could re-write 90% of your bool view state properties as one line triggers.
|
|
|
|
|
SledgeHammer01 wrote: I'm betting I could re-write 90% of your bool view state properties as one line triggers.
I will decline that bet thanks.
How would you handle setting the visibility based on the value of a field?
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Here is part of one I wrote for a custom control. It's not a one liner obviously because it's more complicated, but its setting the visibility based on *4* conditions .
<DataTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Value="1">
<Condition.Binding>
<MultiBinding Converter="{StaticResource HeaderArrowConverter}">
<Binding RelativeSource="{RelativeSource Mode=TemplatedParent}" />
<Binding Path="View.AllowsSorting" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ctrls:ListViewEx}" />
<Binding Path="View.SortColumn" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ctrls:ListViewEx}" />
<Binding Path="View.SortDirection" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ctrls:ListViewEx}" />
</MultiBinding>
</Condition.Binding>
</Condition>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter TargetName="arrow" Property="Data" Value="{StaticResource HeaderArrowUp}" />
<Setter TargetName="arrow" Property="Visibility" Value="Visible" />
</MultiDataTrigger.Setters>
</MultiDataTrigger>
When the value is returned as 1 from the converter, that trigger executes. I haven't had a case where I have to handle a range of values in one trigger, but I have seen some solutions online for that. Instead of having just "1", you can have something like "> 1 && < 5" or however they specify it.
A simple "one liner":
<Trigger Property="SomeProp" Value="15">
<Setter Property="Visibility" Value="Collapsed" />
</Trigger>
modified 5-Feb-12 18:21pm.
|
|
|
|
|
Interesting, this is not an area I have spent any time exploring (obviously). While I see this as 1 possible (and in this case generic) solution, it is not a simple or straight forward solution. I put this in the bucket of complex but generic code and it *may* be used again so it would be the preferred solution.
I had in mind where the visible condition is based on the content of 1 or more fields, not bools but string or numeric. Something that is really specific to only that one view, I would still use code in the VM to evaluate the current record!
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Mycroft Holmes wrote: I had in mind where the visible condition is based on the content of 1 or more
fields, not bools but string or numeric. Something that is really specific to
only that one view, I would still use code in the VM to evaluate the current
record!
That is what I showed in my more complex example. The multi-converter takes in 4 values and returns a decision based on those 4 values. I only showed you a small portion of that trigger, but there are actually 5 cases "1", "2", "3", "4", "5".
The problem with your solution is that you may leave holes where you update one of the values used in the calculation but forget the OnPropertyChanged("VisibilityForState1"); call.
I have done it your way in the past, but found that I didn't like having to put OnPropertyChanged() calls for 4 or 5 properties all over the place.
Also, I kind of believe that the VM should strictly be for communication between the V and M. Adding a bunch of properties to support the view couples them more closely then they should be.
|
|
|
|
|
SledgeHammer01 wrote: The problem with your solution is that you may leave holes where you update one of the values used in the calculation but forget the OnPropertyChanged("VisibilityForState1"); call. Yeah that is one of the main drawbacks. I often throw all the conditional tests into 1 method and call that from multiple events. Which is basically what you are doing in xaml duh!
I can see some research into triggers are going to be needed!
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Mycroft Holmes wrote: Yeah that is one of the main drawbacks. I often throw all the conditional tests
into 1 method and call that from multiple events. Which is basically what you
are doing in xaml duh! I can see some research into triggers are
going to be needed!
One other thought I had about your approach while I was watching TV was that unless you **really** know the VM and its view bindings and how everything works together, you run the real risk of un-necessary / unintentional (and potentially expensive) screen updates.
By "throwing multiple updates in to one function" as you said, you could unintentionally trigger updates for say a few hundred properties when you just updated one. Maybe not on purpose , but by accident.
By doing this via triggers and self enforcing the rule that only the setter for PropertyA is allowed to put up a OnPropertyChanged("PropertyA") notification (and nothing else), you really mitigate this risk and optimize screen updates. All your setters should of course have "if (_theProp != value) { }" checks.
Now, with my trigger example where I bind to 4 properties in a multivalue converter, and I only change one of them, yeah, its going to call the converter function again, but the other 3 values are already cached by WPF. Also, there is very little overhead as the converter instance is cached as well, so you aren't recreating it.
Heck, you don't even need to do it that way. If your conditions are "basic", you can have a multiple condition trigger without the use of a converter at all.
The reason I had to use a converter there was because the logic that returned 1,2,3,4 or 5 was more complex then XAML allowed.
|
|
|
|
|
SledgeHammer01 wrote: By "throwing multiple updates in to one function" as you said,
No no no no -- multiple criteria for 1 update. Although the possibility does exists for your scenario and yeah it is a very valid argument for the trigger requirement.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Sorry Andy we seemed to have hijacked your thread
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
No need to apologise, I may just have learnt something!
I don't speak Idiot - please talk slowly and clearly
'This space for rent'
Driven to the arms of Heineken by the wife
|
|
|
|
|
For a TreeView I would like my items to contain an image and a string.
I have created a WPF UserControl for this called: TreeNode, which has this declaration C# and XAML codes:
public partial class TreeNode : UserControl
{
public TreeNode()
{
InitializeComponent();
}
public string Header
{
get { return txtNodeHeader.Text; }
set { txtNodeHeader.Text = value; }
}
public Image Image
{
get { return imgNodeImage; }
set { imgNodeImage = value; }
}
}
<UserControl x:Class="TreeViewPicture.TreeNode" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="20"
d:DesignWidth="150">
<StackPanel Orientation="Horizontal">
<Image Name="imgNodeImage" Width="16" Height="16" />
<Separator Width="10" />
<TextBlock Name="txtNodeHeader" Text="NodeHeaderText" />
</StackPanel>
</UserControl>
For my MainWindow I have this XAML codes:
<Window x:Class="TreeViewPicture.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TreeViewPicture"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TreeView Name="tvTree">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Nodes}" DataType="{x:Type local:ImageNode}">
<Grid>
<local:TreeNode Header="{Binding Header}" Image="{Binding Image}" />
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
MainWindow.cs contains a set of classes to define my tree structure:
Base node object for all items in the TreeView:
public abstract class Node
{
ObservableCollection<Node> nodes = new ObservableCollection<Node>();
Image image;
string header;
public Node(string header, BitmapImage image)
{
this.header = header;
this.image = new Image();
this.image.Width = 16;
this.image.Source = image;
}
public string Header
{
get { return header; }
}
public Image Image
{
get { return image; }
}
public ObservableCollection<Node> Nodes
{
get { return nodes; }
}
}
Top level object in tree structure
public class Server : Node
{
public Server(string header, BitmapImage image) : base (header, image)
{
}
}
All other levels in tree structure
public class Gateway : Node
{
public Gateway(string header, BitmapImage image) : base(header, image)
{
}
}
MainWindow class:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
public partial class MainWindow : Window
{
BitmapImage serverImage;
BitmapImage gatewayImage;
public MainWindow()
{
InitializeComponent();
InitImages();
Server server = new Server("Server", serverImage);
Gateway gateway = new Gateway("Gateway", gatewayImage);
ObservableCollection<Node> nodes = new ObservableCollection<Node>();
nodes.Add(server);
server.Nodes.Add(gateway);
tvTree.ItemsSource = nodes;
}
private void InitImages()
{
serverImage = new BitmapImage();
serverImage.BeginInit();
serverImage.UriSource = new Uri(@"C:\Users\TheUser\Images\Server.png");
serverImage.EndInit();
gatewayImage = new BitmapImage();
gatewayImage.BeginInit();
gatewayImage.UriSource = new Uri(@"C:\Users\TheUser\Images\Gateway.png");
gatewayImage.EndInit();
}
}
When I try to run this I get a XamlParseException with the following text:
A 'Binding' cannot be set on the 'Header' property of type 'TreeNode'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
XAML is rather tricky and I cannot make any sense of that and what I'm doing wrong.
If I swop in MainWindow XAML code to use the TextBlock object instead of TreeNode. I can see the items I want in the TreeView, but with no picture of course.
Any help would be very nice.
|
|
|
|
|
Solved the problem with this adjustment:
Node class:
public abstract class Node
{
ObservableCollection<Node> nodes = new ObservableCollection<Node>();
BitmapImage image;
string header;
public Node(string header, BitmapImage image)
{
this.header = header;
this.image = image;
}
public string Header
{
get { return header; }
}
public BitmapImage Image
{
get { return image; }
}
public ObservableCollection<Node> Nodes
{
get { return nodes; }
}
}
MainWindow XAML TreeView:
<TreeView Name="tvTree">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Nodes}" DataType="{x:Type local:Node}">
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Source="{Binding Image}" />
<Separator Width="10" Visibility="Hidden" />
<TextBlock Text="{Binding Header}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Of course is that the easiest solution *face palm*
|
|
|
|
|
I have been trying to understand how the GridSplitter works in WPF, so I have written a few tests using it in various environments. In that process I have noticed some odd behavior. Since my tests are using only binding and are written only with XAML I wonder if what I see is evidence of buggy code within WPF, or if I am doing something that should not be done.
I have a WPF application that opens a Window defined using this xaml, and only the default code behind:
<Window x:Class="GridSplitter.GridSplitterWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="GridSplitter"
Width="580"
Height="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Name="c0"
Width="*" />
<ColumnDefinition Name="c1"
Width="*" />
<ColumnDefinition Name="c2"
Width="*" />
<ColumnDefinition Name="c3"
Width="*" />
<ColumnDefinition Name="c4"
Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Name="col0"
Grid.Row="0"
Grid.Column="0"
Text="Col 0 Actual Width"
TextWrapping="Wrap" />
<TextBlock Grid.Row="1"
Grid.Column="0"
Text="{Binding ElementName=col0,
Path=ActualWidth,
StringFormat=\{0:F\}}" />
<TextBlock Name="col1"
Grid.Row="0"
Grid.Column="1"
Text="Col 1 Actual Width"
TextWrapping="Wrap" />
<TextBlock Grid.Row="1"
Grid.Column="1"
Text="{Binding ElementName=col1,
Path=ActualWidth,
StringFormat=\{0:F\}}" />
<TextBlock Name="col2"
Grid.Row="0"
Grid.Column="2"
Text="Col 2 Actual Width"
TextWrapping="Wrap" />
<TextBlock Grid.Row="1"
Grid.Column="2"
Text="{Binding ElementName=col2,
Path=ActualWidth,
StringFormat=\{0:F\}}" />
<TextBlock Name="col3"
Grid.Row="0"
Grid.Column="3"
Text="Col 3 Actual Width"
TextWrapping="Wrap" />
<TextBlock Grid.Row="1"
Grid.Column="3"
Text="{Binding ElementName=col3,
Path=ActualWidth,
StringFormat=\{0:F\}}" />
<TextBlock Name="col4"
Grid.Row="0"
Grid.Column="4"
Text="Col 4 Actual Width"
TextWrapping="Wrap" />
<TextBlock Grid.Row="1"
Grid.Column="4"
Text="{Binding ElementName=col4,
Path=ActualWidth,
StringFormat=\{0:F\}}" />
<TextBlock Grid.Row="2"
Grid.Column="0"
Text="Width"
TextWrapping="Wrap" />
<TextBox Grid.Row="3"
Grid.Column="0"
Text="{Binding Path=Width,
ElementName=c0,
Mode=TwoWay}" />
<TextBlock Grid.Row="2"
Grid.Column="1"
Text="Width"
TextWrapping="Wrap" />
<TextBox Grid.Row="3"
Grid.Column="1"
Text="{Binding Path=Width,
ElementName=c1,
Mode=TwoWay}" />
<TextBlock Grid.Row="2"
Grid.Column="2"
Text="Width"
TextWrapping="Wrap" />
<TextBox Grid.Row="3"
Grid.Column="2"
Text="{Binding Path=Width,
ElementName=c2,
Mode=TwoWay}" />
<TextBlock Grid.Row="2"
Grid.Column="3"
Text="Width"
TextWrapping="Wrap" />
<TextBox Grid.Row="3"
Grid.Column="3"
Text="{Binding Path=Width,
ElementName=c3,
Mode=TwoWay}" />
<TextBlock Grid.Row="2"
Grid.Column="4"
Text="Width"
TextWrapping="Wrap" />
<TextBox Grid.Row="3"
Grid.Column="4"
Text="{Binding Path=Width,
ElementName=c4,
Mode=TwoWay}" />
<GridSplitter Grid.RowSpan="4"
Grid.Column="2"
Width="4"
VerticalAlignment="Stretch" />
</Grid>
</Window>
The Binding does two things: (1) It tells me what is the ActualWidth of the columns. (I am actually binding to Label s that have their Width property set to "Auto" . When I tried to bind to the ActualWidth of the ColumnDefinition tags, I started seeing some of the behavior I'll describe below, so I thought I'd try this as a workaround.) (2) It allows me to change the Width property of the columns during run time.
When I compile and execute and use the GridSpliter , several things occur that I think should not. To cut to the chase I'll enumerate:
1. If you run the window just as I have written it, and then move the GridSplitter to the left, the third column collapses unexpectedly hiding most of its contents. (Strike this. I've just discovered why this happens, but I'll wait before I explain. It might be a nice puzzle to figure out.)
2. If all of the columns are given a Width of Auto , it is possible to push the two left columns beyond the right edge of the Window , and even beyond so that the GridSplitter could not be grabbed by the mouse, if it was dropped there.
3. If the two outer columns on both sides are given a Width of 100, and the middle column is given a Width of "*", it is possible to move the GridSplitter to the left of the middle column and this results in pushing the two columns on the right to the right, again right off the Window !
Item #1 I know is because of the Binding and the design of the window, so I would not consider it evidence of a bug in Microsoft's code. But what of #2 and #3? Is that a result of something I wrote in XAML, or is it due to poor validation in the Grid and GridSplitter code?
When I saw this I thought of CodePlex, and wondered if users here would be intrigued with this strange behavior. So, what do you think?
|
|
|
|
|