问题描述
我正在尝试将各种滑块元素组合在一起。例如,如果我有两个元素,两个元素都设置为50(值从0到100),则值的总和必须始终为100,因此,如果将其中一个滑块设置为值70,则另一个必须动态减小到30的值。
<ListView x:Name="listView"
ItemSource="myList">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Slider x:Name="slider"
Maximum="100"
Minimum="0"
Value="{Binding MyValue}"
HorizontalOptions="FillAndExpand"
MinimumTrackColor="Black"
MaximumTrackColor="Black"
ThumbColor="{StaticResource myColor}"
ValueChanged="OnValueChanged"
PropertyChanging="ChangingSliderValue"/>
<Label Text="{Binding Source={x:Reference slider},Path=Value,StringFormat='{0:0}'}"
FontSize="Medium"
FontAttributes="Bold"
HorizontalOptions="End"
WidhtRequest="40"/>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
我对象的C#类是
public class MyClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int _value;
private string _name;
private bool _someBool;
public int MyValue { get {return _value;} set {_value = value;} }
public string Name { get {return _name;} set {_name = value;} }
public bool SomeBool { get {return _someBool;} set {_someBool = value; OnPropertyChanged();} }
void OnPropertyChanged ([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this,new PropertyChangedEventArgs(propertyName));
}
}
}
namespace MyApp
{
[XamlCompilation(XamlCompilationoptions.Compile)]
public partial class SliderPage: ContentPage
{
private ObservableCollection<MyClass> list = new ObservableCollection<MyClass>();
...
public SliderPage ()
{
InitializeComponent();
InitList();
listView.ItemsSource = list;
...
}
private void InitList () ...
private void ChangingSliderValue (object sender,PropertyChangedEventArgs e)
{
//Code to stick together the slider...
}
}
关于如何实现我的目标的任何建议?
解决方法
工作,但没有动态显示
您需要在属性 MyValue 上实现接口 INotifyPropertyChanged ,以便该元素在运行时更新。
顺便说一句,因为您在项目中使用了数据绑定。最好在ViewModel中处理逻辑。因此,您可以像下面这样修改代码
在Xmal
<ListView
ItemsSource="{Binding MySource}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal" HeightRequest="300" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Slider x:Name="slider"
Maximum="100"
Minimum="0"
Value="{Binding MyValue,Mode=TwoWay}"
HorizontalOptions="FillAndExpand"
MinimumTrackColor="Black"
MaximumTrackColor="Black"/>
<Label Text="{Binding Source={x:Reference slider},Path=Value,StringFormat='{0:0}'}"
FontSize="20"
FontAttributes="Bold"
WidthRequest="40"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
在后面的代码中
型号
public class MyClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public int Id { get; set; } // add this property to index the slider
private int _value;
private string _name;
private bool _someBool;
public int MyValue {
get
{
return _value;
}
set
{
if(_value!=value)
{
_value = value;
OnPropertyChanged("MyValue");
}
}
}
public string Name { get { return _name; } set { _name = value; } }
public bool SomeBool { get { return _someBool; } set { _someBool = value; OnPropertyChanged("SomeBool"); } }
void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this,new PropertyChangedEventArgs(propertyName));
}
}
}
ViewModel
public class MyViewModel
{
public ObservableCollection<MyClass> MySource { get; set; }
bool isFirstLoad = true;
public MyViewModel()
{
MySource = new ObservableCollection<MyClass>() {
new MyClass(){MyValue = 50,Id=0 },new MyClass(){MyValue = 50,Id=1 },};
foreach (MyClass model in MySource)
{
model.PropertyChanged += Model_PropertyChanged;
}
}
private void Model_PropertyChanged(object sender,PropertyChangedEventArgs e)
{
if (e.PropertyName== "MyValue")
{
//handle your logic here as you need
MyClass model = sender as MyClass;
foreach (MyClass item in MySource)
{
if (model.Id != item.Id)
{
item.MyValue = 100 - model.MyValue;
}
}
}
}
}
ContentPage
public xxxPage()
{
InitializeComponent();
BindingContext = new MyViewModel();
}