Trying to get IsEnabled to bind to Dependency Property - c#

Any idea where I'm going wrong with this code. I want the TextBox to be Enabled when the associated RadioButton for it is selected, and then when a different radio button is selected I want it to be Enabled=False. I created a ProxyMode dependency property and have changed the getter to obtain it's bool value based on whether Proxy is selected or not. Doesn't seem to work...any ideas?
// Proxy Host Name
public string Proxy
{
get { return (string)GetValue(ProxyProperty); }
set { SetValue(ProxyProperty, value); }
}
public static readonly DependencyProperty ProxyProperty =
DependencyProperty.Register("Proxy", typeof(string), typeof(ConfigWindowViewModel), new UIPropertyMetadata("[e.g. proxy.mycompany.com]"));
public bool ProxyMode
{
get { return Proxy == "Proxy"; }
set { SetValue(ProxyModeProperty, value); }
}
public static readonly DependencyProperty ProxyModeProperty =
DependencyProperty.Register("ProxyMode", typeof(bool), typeof(ConfigWindowViewModel));
And the XAML
<StackPanel Grid.Column="0" Margin="2">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<RadioButton IsChecked="{Binding Path=Mode, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Proxy}"
VerticalAlignment="Center"
Padding="2,0,10,0">Proxy
</RadioButton>
<TextBox Text="{Binding Path=Proxy}"
IsEnabled="{Binding Path=ProxyMode}"
Width="Auto"
Name="ProxyHostTextBox"
VerticalAlignment="Center"
MinWidth="150"
/>
</StackPanel>
<RadioButton IsChecked="{Binding Path=Mode, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Direct}">Direct</RadioButton>
</StackPanel>

The easiest way to enable/disable the textbox based on whether the proxy RadioButton is checked is to bind the IsEnabled property of the TextBox directly to the IsChecked property of the proxy RadioButton. Assuming the proxy RadioButton is named "proxy":
<TextBox Text="{Binding Path=Proxy}" IsEnabled="{Binding ElementName=proxy, Path=IsChecked}"/>
If you meant for your RadioButton controls to be linked so that only one can be selected at once, you need to set the GroupName property to something on both of them (it should be the same for all linked RadioButton controls).
Let me know if you have further questions.

As with the second version of this question:
<RadioButton x:Name="RadioButton2" />
<TextBox IsEnabled="{Binding IsChecked, ElementName=RadioButton2}" />

think I came up with a better way to do this - so the question probably isn't a good one to ask - the following without dependency property seem ok
<StackPanel Grid.Column="0" Margin="2">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<RadioButton IsChecked="{Binding Path=Mode, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Proxy}" VerticalAlignment="Center" Padding="2,0,10,0" Name="ProxyModeRadioButton">Proxy</RadioButton>
<TextBox Text="{Binding Path=Proxy}"
IsEnabled="{Binding ElementName=ProxyModeRadioButton, Path=IsChecked}"
Width="Auto" Name="ProxyHostTextBox" VerticalAlignment="Center" MinWidth="150"
/>
</StackPanel>
<RadioButton IsChecked="{Binding Path=Mode, Converter={StaticResource enumBooleanConverter}, ConverterParameter=Direct}">Direct</RadioButton>
</StackPanel>

Related

WPF ListView items binding to each other

I have a listview in WPF which holds an observable collection of objects.
The objects are simple rectangular boxes containing a set of radio buttons:
The two sets of radio buttons are kept separate by setting the 'GroupName' in xaml to either GroupName="Numbers" or GroupName="Letters"
--EDIT--
As requested, here is the code within MyObject for the radiobuttons:
<RadioButton Grid.Column="1" Grid.Row="1" GroupName="Numbers" IsChecked="{Binding IsOne, Mode=TwoWay}" />
<RadioButton Grid.Column="2" Grid.Row="1" GroupName="Numbers" IsChecked="{Binding IsOne, Converter={StaticResource NegateBoolConverter}, Mode=TwoWay}" />
<RadioButton Grid.Column="1" Grid.Row="2" GroupName="Letters" IsChecked="{Binding IsA, Mode=TwoWay}" />
<RadioButton Grid.Column="2" Grid.Row="2" GroupName="Letters" IsChecked="{Binding IsA, Converter={StaticResource NegateBoolConverter}, Mode=TwoWay}" />
Negate bool converter simply returns the inverse of the bool value.
--End Edit--
The problem comes when I have a list of two of these objects in my list view. The first object (object 1) for example has 'One' and 'A' selected.
If I then select 'B' in object 2, the selection will try and change for object 1 as well (which messes everything up)
Here is an example of what I am hoping to achieve:
Has anyone seen this behaviour? On winforms it's fixed by setting a new BindingContext for each item but I don't know whether this is the same in WPF.
I am working in a fully MVVM environment, here is the code for the listview:
<ListView Name="ObjectsListView" ItemsSource="{Binding MyObjectList}" SelectedItem="{Binding SelectedObject, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ContentControl>
<local:MyObject DataContext="{Binding}"/>
</ContentControl>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Please can someone let me know how to achieve separate behaviour in my listview items?
Thank you in advance.
Problem is that each item of listview creates radiobutton which the same GroupName, in wpf it is only possible to select one radiobutton from group.
So if you got two items ore more the radiobuttons will belong to one common Group.
Solution:
I add two new properties to Model (your class of SelectObject)
private string _NameFirst;
public string NameFirst
{
get { return _NameFirst; }
set
{
if (value != _NameFirst)
{
_NameFirst = value;
NotifyPropertyChanged();
}
}
}
private string _NameSecond;
public string NameSecond
{
get { return _NameSecond; }
set
{
if (value != _NameSecond)
{
_NameSecond = value;
NotifyPropertyChanged();
}
}
}
Each model item of the list should have different NameFirst and NameSecond, there are multiple ways to do so. E.g item1 : (NameFirst="A1",NameSecond="B1"), item2 : (NameFirst="A2", NameSecond="B2".
Also I modify the ContentControl of ListView I modified to StackPanel only for simplicity, you can stay with grid as well.
<StackPanel>
<RadioButton Grid.Column="0" Content="One" Grid.Row="0" GroupName="{Binding NameFirst}" IsChecked="{Binding IsOne, Mode=TwoWay}" />
<RadioButton Content="Two" GroupName="{Binding NameFirst}" IsChecked="{Binding IsOne, Converter={StaticResource NegateBoolConverter}, Mode=TwoWay}" />
<RadioButton Content="A" GroupName="{Binding NameSecond}" IsChecked="{Binding IsA, Mode=TwoWay}" />
<RadioButton Content="B" GroupName="{Binding NameSecond}" IsChecked="{Binding IsA, Converter={StaticResource NegateBoolConverter}, Mode=TwoWay}" />
</StackPanel>

How to use data templates in xaml

I have a data context class with complex fields (objects). Each object has a double and boolean field and some more fancy info. I also have two data templates, one for a double value to represent it as a slider and another one to represent a bool field as check box. How do I write the xaml to use the two already existing data templates I have? The problem is that the data context class can have fields which are not those objects containing a double and boolean value.
I am a newbie but I know how bindings and data context works.
Some code:
Class MyDataContext
{
public MyWpfField field1;
public WeirdField field1;
public MyWpfField field1;
public WeirdField field1;
}
Class MyWpfField
{
public string niceName;
public bool isEnable;
public double data;
.
.
.
}
Some xaml:
<DataTemplate x:Key="DataBoolTmpl">
<StackPanel
Margin="{StaticResource DefaultSpacing}"
Orientation="Horizontal"
ToolTip="{Binding ....}">
<CheckBox
IsEnabled="{Binding ...}"
Visibility="{Binding ...}"
IsChecked="{Binding ...}" />
<TextBlock Text="{Binding niceName}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="DataTmplSlider">
<StackPanel
IsEnabled="{Binding ...}"
Margin="{StaticResource DefaultSpacing}"
ToolTip="{Binding ...}" >
<TextBlock Text="{Binding niceName}" />
<StackPanel Orientation="Horizontal"
Margin="{StaticResource DefaultSpacing}">
<TextBlock Text="{Binding ...}" MinWidth="40"/>
<TextBlock Text="{Binding ...}"/>
<Slider
Margin="5,0,0,0"
Visibility="{Binding ...}"
Minimum="{Binding ...}"
Maximum="{Binding ...}"
IsSnapToTickEnabled="True"
SmallChange="{Binding ...}"
MinWidth="100"
MinHeight="15">
<Slider.Value>
<Binding ...}"/>
</Slider.Value>
</Slider>
</StackPanel>
</StackPanel>
</DataTemplate>
Adapted from this answer: https://stackoverflow.com/a/755177/1783619
Use a ContentControl to utilize your data templates:
<ContentControl ContentTemplate="{StaticResource ..}" Content="{Binding MyField}"/>
You'll create one for each field. For more information, see MSDN.

Textbox not updating

Ive tried searching, but maybe im not using the right terms to search for.
I have several textboxes that im using, and when i enter data, i see the values being updated when debugging, but they never get updated to the form.
Basically, I have a form that is used for the visuals, and then i have a class that handles all the activity. I have created the class as a resource, and I am referencing to the resource within the textboxes.
The only way that i really knew how to handle the updating of the forms was by implementing the calculations on values changing. So if I updated a property, I called the method from OnPropertyChanged(). This created issues because the values were always getting changed due to the calculations rewriting values. I then tried evaluating the changes of the new value
I.E.
public double In1
{
get{_return _in1;}
set{
if (_in1 != value)
_in1 = value;
OnPropertyChanged("In1");
}
}
regardless of anything, my problem is that i dont see the values getting written to the textbox. This is my first real endevour of using data binding so im assuming that im doing something incorrectly (clearly)
<ad:DockableContent
xmlns="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="DMC_Robot_Editor.GUI.frmAngleConvertor"
Title="frmAngleConvertor" Height="259" Width="282">
<ad:DockableContent.Resources>
<local:AngleConvertor x:Key="Converter"/>
</ad:DockableContent.Resources>
<Grid >
<GroupBox HorizontalAlignment="Stretch" VerticalAlignment="Top">
<Grid>
<ComboBox x:Name="cbInput" HorizontalAlignment="Stretch" VerticalAlignment="Top" Grid.Column="1" Grid.ColumnSpan="3" Grid.Row="1" DisplayMemberPath="ValueCartesianString" SelectedValuePath="ValueCartesianEnum" IsSynchronizedWithCurrentItem="True" SelectedIndex="{Binding InputItem,Source={StaticResource Converter}}" ItemsSource="{Binding InputConvention, Source={StaticResource Converter}}" IsReadOnly="True"/>
<TextBox x:Name="tbIn1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Text="{Binding In1, Converter={StaticResource DoubleToStringConverter}, Source={StaticResource Converter}}" Grid.Column="0" d:LayoutOverrides="GridBox" Grid.Row="2" Width="50" TextAlignment="Center">
<TextBox.DataContext>
<local:AngleConvertor/>
</TextBox.DataContext> </Grid>
</ad:DockableContent>
public class AngleConverter()
{
private double _in1 = 0.0;
public double In1
{
get{_return _in1;}
set{
if (_in1 != value)
_in1 = value;
OnPropertyChanged("In1");
}
}
}
Try to apply UpdateSourceTrigger=PropertyChanged on your text box:
Text="{Binding Path-In1, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource DoubleToStringConverter}, Source={StaticResource Converter}}"
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
You can add to your binding UpdateSourceTrigger=PropertyChanged with your Mode TwoWay
<TextBox Name="tbIn1"
HorizontalAlignment="Center"
VerticalAlignment="Bottom"
Text="{Binding In1, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource DoubleToStringConverter},
Source={StaticResource Converter}}"
Grid.Column="0"
d:LayoutOverrides="GridBox"
Grid.Row="2"
Width="50"
TextAlignment="Center"
/>
your real code should have something like this:
public class AngleConverter : INotifyPropertyChanged
so i assume its just a typo in your code. you did not post your converter code, the binding in your textbox is ok. Textbox default UpdateSourceTrigger is lostfocus. so maybe UpdateSourceTrigger=PropertyChanged did what you want.
Review the binding
Does DoubleToStringConverter get called?
Is get called?
Text="{Binding In1, Converter={StaticResource DoubleToStringConverter}, Source={StaticResource Converter}}"
Move Source out of binding in into DataContext on the DockableContent.
DataContext="{Binding RelativeSource={RelativeSource self}}"
Try with no converter
Text="{Binding In1}"

WPF DataTemplate method binding with parameter

I have a custom ItemTemplate for a ListBox and I need to "bind" a TextBlock to some special method / property.
My ListBox Source is an ObservableCollection<SearchResultItem>. SearchResultItem containing some properties.
The text need to change based on the value of another object. E.G if this object equals "foo" I need the text value to call the method GetProperty("foo") on the SearchResultItem to get the correct value.
Here is a sample of code:
<DataTemplate>
..
//Here is a Label bound to the Date Property of the SearchResultItem
<Label Margin="2,2,2,0" Grid.Row="0" Grid.Column="2" Content="{Binding Path=Date}" HorizontalAlignment="Right" HorizontalContentAlignment="Right" />
//Here is the textblock that needs to call the method with the parameter based on the value of the other object.
<TextBlock Margin="2,2,2,0" TextTrimming="CharacterEllipsis" Grid.Row="0" Grid.Column="1" Text="I need some help there" HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="Black"/>
..
</DataTemplate>
Do you have any idea on how to do that or a better way to do it?
Edit:
-Let's assume SearchResultItem comes from an external library and only exposes the GetProperty method.
-Let's say the "foo" value comes from ConfigurationManager.AppSettings["propertyName"]; if it helps.
OK, because your properties never change, here's one solution. You can do this via another property on your SearchResultItem class:
public string MyTextBinding
{
get
{
return myDictionary.ContainsKey("foo") ? return myDictionary["foo"] : return "myDictionary doesn't contain foo";
}
}
Then just bind your textbox to this property:
<DataTemplate>
<Label Margin="2,2,2,0" Grid.Row="0" Grid.Column="2" Content="{Binding Path=Date}" HorizontalAlignment="Right" HorizontalContentAlignment="Right" />
<TextBlock Margin="2,2,2,0" TextTrimming="CharacterEllipsis" Grid.Row="0" Grid.Column="1" Text="{Binding Path=MyTextBinding, Mode=OneWay}" HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="Black"/>
</DataTemplate>
Just use a IValueConverter that takes a SearchResultItem and return the expected text
<TextBlock Margin="2,2,2,0" TextTrimming="CharacterEllipsis"
Grid.Row="0" Grid.Column="1"
Text="{Binding Path=.,
Converter={StaticResource PropertyValueFromSearchResultItemConverter},
ConverterParameter=Foo}"
HorizontalAlignment="Left" VerticalAlignment="Center" Foreground="Black"/>

How do I hide the empty tooltip in Silverlight?

I have a TextBlock with a tooltip that displays the same data, in case of truncation. However if the property that TextBlock.Text and the tooltip's text are bound to is empty (null or zero length string) the tooltip appears as a small empty box. Is there a way to hide this and show no tooltip in this case?
<TextBlock Text="{Binding Text}">
<util:ToolTipManager.ToolTip>
<TextBlock TextWrapping="Wrap" Text="{Binding Text}" />
</util:ToolTipManager.ToolTip>
</TextBlock>
I have tried using a StringToVisibilityConverter by adding Visibility="{Binding Text, Converter={StaticResource StringToVisConverter}}" to the TextBlock without any luck.
I also tried implementing the answer given Hide tooltip if binding is null but that seems specific to their set-up (or at least I haven't figured out how to adapt it successfully).
(ToolTipManager is from http://www.codeproject.com/Articles/36078/Silverlight-2-0-How-to-use-a-DataBinding-with-the, used to provide the data binding for the tooltip.)
Edit:
In response to the comments, here is the XAML I tried for the related question mentioned above:
<TextBlock Text="{Binding PointName}">
<local:ToolTipManager.ToolTip>
<Grid>
<TextBlock TextWrapping="Wrap" Text="{Binding PointName}"/>
<Rectangle Fill="Transparent" Visibility="{Binding PointName, Converter={StaticResource StringToVisConverter}}" />
</Grid>
</local:ToolTipManager.ToolTip>
</TextBlock>
And here is my String to Visibility converter code:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string visible = (string)value;
return (!String.IsNullOrWhiteSpace(visible) ? Visibility.Visible : Visibility.Collapsed);
}
I assume you are using Siverlight 4 as it is one of your tags.
In Silverlight 4, I am pretty sure that you don't need the ToolTipManager anymore.
You can just wrap the Rectangle and the TextBlock with a Grid, like this,
<Grid>
<TextBlock Text="{Binding PointName}"/>
<Rectangle Fill="Transparent" Visibility="{Binding PointName, Converter={StaticResource BooleanToVisibilityConverter}}" ToolTipService.ToolTip="{Binding PointName}"/>
</Grid>
UPDATE:
<Grid>
<TextBlock Text="{Binding PointName}"/>
<Rectangle Fill="Transparent" Visibility="{Binding PointName, Converter={StaticResource BooleanToVisibilityConverter}}">
<ToolTipService.ToolTip>
<TextBlock TextWrapping="Wrap" Text="{Binding PointName}"/>
</ToolTipService.ToolTip>
</Rectangle>
</Grid>
If you are using Silverlight 5, the following seems to work:
<ToolTipService.ToolTip>
<ToolTip Visibility="{Binding WhatDeterminesTooltipVisibility}">
<Border Background="Azure" Width="100" />
</ToolTip>
</ToolTipService.ToolTip>

Categories

Resources